From 25e3cfac15f41834db473f039e21b7a4ff15279b Mon Sep 17 00:00:00 2001 From: Yaroslav Bolyukin Date: Mon, 19 Sep 2022 12:58:54 +0000 Subject: [PATCH] Merge pull request #548 from UniqueNetwork/feature/multi-assets-redone Feature/multi assets redone --- --- /dev/null +++ b/.docker/Dockerfile-acala.j2 @@ -0,0 +1,41 @@ +# ===== Rust builder ===== +FROM ubuntu:20.04 as rust-builder +LABEL maintainer="Unique.Network" + +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 llvm libudev-dev && \ + 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 ACALA ===== +FROM rust-builder as builder-acala-bin + +WORKDIR /unique_parachain + +RUN git clone -b {{ ACALA_BUILD_BRANCH }} --depth 1 https://github.com/AcalaNetwork/Acala.git && \ + cd Acala && \ + make init && \ + make build-release + +# ===== BIN ====== + +FROM ubuntu:20.04 as builder-acala + +COPY --from=builder-acala-bin /unique_parachain/Acala/target/production/acala /unique_parachain/Acala/target/production/acala --- /dev/null +++ b/.docker/Dockerfile-cumulus.j2 @@ -0,0 +1,40 @@ +# ===== Rust builder ===== +FROM ubuntu:20.04 as rust-builder +LABEL maintainer="Unique.Network" + +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 llvm libudev-dev && \ + 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 CUMULUS ===== +FROM rust-builder as builder-cumulus-bin + +WORKDIR /unique_parachain + +RUN git clone -b {{ CUMULUS_BUILD_BRANCH }} --depth 1 https://github.com/paritytech/cumulus.git && \ + cd cumulus && \ + cargo build --release + +# ===== BIN ====== + +FROM ubuntu:20.04 as builder-cumulus + +COPY --from=builder-cumulus-bin /unique_parachain/cumulus/target/release/polkadot-parachain /unique_parachain/cumulus/target/release/polkadot-parachain --- /dev/null +++ b/.docker/Dockerfile-moonbeam.j2 @@ -0,0 +1,41 @@ +# ===== Rust builder ===== +FROM ubuntu:20.04 as rust-builder +LABEL maintainer="Unique.Network" + +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 llvm libudev-dev && \ + 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 MOONBEAM ===== +FROM rust-builder as builder-moonbeam-bin + +WORKDIR /unique_parachain + +RUN git clone -b {{ MOONBEAM_BUILD_BRANCH }} --depth 1 https://github.com/PureStake/moonbeam.git && \ + cd moonbeam && \ + cargo build --release + +# ===== BIN ====== + +FROM ubuntu:20.04 as builder-moonbeam + +COPY --from=builder-moonbeam-bin /unique_parachain/moonbeam/target/release/moonbeam /unique_parachain/moonbeam/target/release/moonbeam \ No newline at end of file --- /dev/null +++ b/.docker/Dockerfile-polkadot.j2 @@ -0,0 +1,40 @@ +# ===== Rust builder ===== +FROM ubuntu:20.04 as rust-builder +LABEL maintainer="Unique.Network" + +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 llvm libudev-dev && \ + 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 POLKADOT ===== +FROM rust-builder as builder-polkadot-bin + +WORKDIR /unique_parachain + +RUN git clone -b {{ POLKADOT_BUILD_BRANCH }} --depth 1 https://github.com/paritytech/polkadot.git && \ + cd polkadot && \ + cargo build --release + +# ===== BIN ====== + +FROM ubuntu:20.04 as builder-polkadot + +COPY --from=builder-polkadot-bin /unique_parachain/polkadot/target/release/polkadot /unique_parachain/polkadot/target/release/polkadot --- /dev/null +++ b/.docker/Dockerfile-xcm.j2 @@ -0,0 +1,85 @@ +# ===== Rust builder ===== +FROM ubuntu:20.04 as rust-builder +LABEL maintainer="Unique.Network" + +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 llvm libudev-dev && \ + 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 ====== +FROM rust-builder as builder-unique + +ARG PROFILE=release + +WORKDIR /unique_parachain + +COPY ./xcm-config/launch-config-xcm-{{ NETWORK }}.json ./launch-config-xcm-{{ NETWORK }}.json +COPY ./xcm-config/5validators.jsonnet ./5validators.jsonnet +COPY ./xcm-config/minBondFix.jsonnet ./minBondFix.jsonnet + +RUN git clone -b {{ BRANCH }} https://github.com/UniqueNetwork/unique-chain.git && \ + cd unique-chain && \ + cargo build --features={{ FEATURE }} --$PROFILE + +# ===== RUN ====== + +FROM ubuntu:20.04 + +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 {{ POLKADOT_LAUNCH_BRANCH }} + +RUN export NVM_DIR="$HOME/.nvm" && \ + [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" && \ + cd /polkadot-launch && \ + npm install --global yarn && \ + yarn install + +COPY --from=builder-unique /unique_parachain/launch-config-xcm-{{ NETWORK }}.json /polkadot-launch/ +COPY --from=builder-unique /unique_parachain/5validators.jsonnet /polkadot-launch/5validators.jsonnet +COPY --from=builder-unique /unique_parachain/minBondFix.jsonnet /polkadot-launch/minBondFix.jsonnet + +COPY --from=builder-unique /unique_parachain/unique-chain/target/release/unique-collator /unique-chain/target/release/ + +COPY --from=uniquenetwork/builder-polkadot:{{ POLKADOT_BUILD_BRANCH }} /unique_parachain/polkadot/target/release/polkadot /polkadot/target/release/ +COPY --from=uniquenetwork/builder-moonbeam:{{ MOONBEAM_BUILD_BRANCH }} /unique_parachain/moonbeam/target/release/moonbeam /moonbeam/target/release/ +COPY --from=uniquenetwork/builder-cumulus:{{ CUMULUS_BUILD_BRANCH }} /unique_parachain/cumulus/target/release/polkadot-parachain /cumulus/target/release/cumulus +COPY --from=uniquenetwork/builder-acala:{{ ACALA_BUILD_BRANCH }} /unique_parachain/Acala/target/production/acala /acala/target/release/ +COPY --from=uniquenetwork/builder-chainql:latest /chainql/target/release/chainql /chainql/target/release/ + +EXPOSE 9844 +EXPOSE 9933 +EXPOSE 9944 +EXPOSE 9946 +EXPOSE 9947 +EXPOSE 9948 + +CMD export NVM_DIR="$HOME/.nvm" PATH="$PATH:/chainql/target/release" && \ + [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" && \ + cd /polkadot-launch && \ + yarn start launch-config-xcm-{{ NETWORK }}.json + --- /dev/null +++ b/.docker/docker-compose.tmp-xcm-tests.j2 @@ -0,0 +1,25 @@ +version: "3.5" + +services: + xcm_nodes: + image: uniquenetwork/xcm-{{ NETWORK }}-testnet-local:latest + container_name: xcm-{{ NETWORK }}-testnet-local + expose: + - 9844 + - 9933 + - 9944 + - 9946 + - 9947 + - 9948 + ports: + - 127.0.0.1:9844:9844 + - 127.0.0.1:9933:9933 + - 127.0.0.1:9944:9944 + - 127.0.0.1:9946:9946 + - 127.0.0.1:9947:9947 + - 127.0.0.1:9948:9948 + logging: + options: + max-size: "1m" + max-file: "3" + --- /dev/null +++ b/.docker/xcm-config/5validators.jsonnet @@ -0,0 +1,50 @@ + +function(spec) + spec { + genesis+: { + runtime+: { + staking+: { + validatorCount: 5, + invulnerables: [ + '5GNJqTPyNqANBkUVMN1LPPrxXnFouWXoe2wNSmmEoLctxiZY', + '5HpG9w8EBLe5XCrbczpwq5TSXvedjrBGCwqxK1iQ7qUsSWFc', + '5Ck5SLSHYac6WFt5UZRSsdJjwmpSZq85fd5TRNAdZQVzEAPT', + '5HKPmK9GYtE1PSLsS1qiYU9xQ9Si1NcEhdeCq9sw5bqu4ns8', + '5FCfAonRZgTFrTd9HREEyeJjDpT397KMzizE6T3DvebLFE7n', + ], + stakers: [ + [ + '5GNJqTPyNqANBkUVMN1LPPrxXnFouWXoe2wNSmmEoLctxiZY', + '5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY', + 100000000000000, + 'Validator', + ], + [ + '5HpG9w8EBLe5XCrbczpwq5TSXvedjrBGCwqxK1iQ7qUsSWFc', + '5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty', + 100000000000000, + 'Validator', + ], + [ + '5Ck5SLSHYac6WFt5UZRSsdJjwmpSZq85fd5TRNAdZQVzEAPT', + '5FLSigC9HGRKVhB9FiEo4Y3koPsNmBmLJbpXg2mp1hXcS59Y', + 100000000000000, + 'Validator', + ], + [ + '5HKPmK9GYtE1PSLsS1qiYU9xQ9Si1NcEhdeCq9sw5bqu4ns8', + '5DAAnrj7VHTznn2AWBemMuyBwZWs6FNFjdyVXUeYum3PTXFy', + 100000000000000, + 'Validator', + ], + [ + '5FCfAonRZgTFrTd9HREEyeJjDpT397KMzizE6T3DvebLFE7n', + '5HGjWAeFDfFCWPsjFQdVV2Msvz2XtMktvgocEZcCj68kUMaw', + 100000000000000, + 'Validator', + ], + ], + }, + }, + }, + } --- /dev/null +++ b/.docker/xcm-config/launch-config-xcm-opal.json @@ -0,0 +1,134 @@ +{ + "relaychain": { + "bin": "/polkadot/target/release/polkadot", + "chain": "westend-local", + "chainInitializer": [ + "chainql", + "--tla-code=spec=import '${spec}'", + "5validators.jsonnet" + ], + "nodes": [ + { + "name": "alice", + "wsPort": 9844, + "rpcPort": 9843, + "port": 30444, + "flags": [ + "--unsafe-rpc-external", + "--unsafe-ws-external", + "-lparachain::candidate_validation=debug" + ] + }, + { + "name": "bob", + "wsPort": 9855, + "rpcPort": 9854, + "port": 30555, + "flags": [ + "--unsafe-rpc-external", + "--unsafe-ws-external", + "-lparachain::candidate_validation=debug" + ] + }, + { + "name": "charlie", + "wsPort": 9866, + "rpcPort": 9865, + "port": 30666, + "flags": [ + "--unsafe-rpc-external", + "--unsafe-ws-external", + "-lparachain::candidate_validation=debug" + ] + }, + { + "name": "dave", + "wsPort": 9877, + "rpcPort": 9876, + "port": 30777, + "flags": [ + "--unsafe-rpc-external", + "--unsafe-ws-external", + "-lparachain::candidate_validation=debug" + ] + }, + { + "name": "eve", + "wsPort": 9888, + "rpcPort": 9887, + "port": 30888, + "flags": [ + "--unsafe-rpc-external", + "--unsafe-ws-external", + "-lparachain::candidate_validation=debug" + ] + } + + ], + "genesis": { + "runtime": { + "runtime_genesis_config": { + "parachainsConfiguration": { + "config": { + "validation_upgrade_frequency": 1, + "validation_upgrade_delay": 1 + } + } + } + } + } + }, + "parachains": [ + { + "bin": "/unique-chain/target/release/unique-collator", + "id": "2095", + "balance": "1000000000000000000000000", + "nodes": [ + { + "port": 31200, + "wsPort": 9944, + "rpcPort": 9933, + "name": "alice", + "flags": [ + "--unsafe-rpc-external", + "--unsafe-ws-external" + ] + } + ] + }, + { + "bin": "/cumulus/target/release/cumulus", + "id": "1000", + "chain": "westmint-local", + "balance": "1000000000000000000000000", + "nodes": [ + { + "wsPort": 9948, + "port": 31204, + "name": "alice", + "flags": [ + "--unsafe-rpc-external", + "--unsafe-ws-external" + ] + } + ] + } + ], + "simpleParachains": [], + "hrmpChannels": [ + { + "sender": 2095, + "recipient": 1000, + "maxCapacity": 8, + "maxMessageSize": 512 + }, + { + "sender": 1000, + "recipient": 2095, + "maxCapacity": 8, + "maxMessageSize": 512 + } + ], + "finalization": false +} + --- /dev/null +++ b/.docker/xcm-config/launch-config-xcm-quartz.json @@ -0,0 +1,199 @@ +{ + "relaychain": { + "bin": "/polkadot/target/release/polkadot", + "chain": "westend-local", + "chainInitializer": [ + "chainql", + "--tla-code=spec=import '${spec}'", + "5validators.jsonnet" + ], + "nodes": [ + { + "name": "alice", + "wsPort": 9844, + "rpcPort": 9843, + "port": 30444, + "flags": [ + "--unsafe-rpc-external", + "--unsafe-ws-external", + "-lparachain::candidate_validation=debug" + ] + }, + { + "name": "bob", + "wsPort": 9855, + "rpcPort": 9854, + "port": 30555, + "flags": [ + "--unsafe-rpc-external", + "--unsafe-ws-external", + "-lparachain::candidate_validation=debug" + ] + }, + { + "name": "charlie", + "wsPort": 9866, + "rpcPort": 9865, + "port": 30666, + "flags": [ + "--unsafe-rpc-external", + "--unsafe-ws-external", + "-lparachain::candidate_validation=debug" + ] + }, + { + "name": "dave", + "wsPort": 9877, + "rpcPort": 9876, + "port": 30777, + "flags": [ + "--unsafe-rpc-external", + "--unsafe-ws-external", + "-lparachain::candidate_validation=debug" + ] + }, + { + "name": "eve", + "wsPort": 9888, + "rpcPort": 9887, + "port": 30888, + "flags": [ + "--unsafe-rpc-external", + "--unsafe-ws-external", + "-lparachain::candidate_validation=debug" + ] + } + + ], + "genesis": { + "runtime": { + "runtime_genesis_config": { + "parachainsConfiguration": { + "config": { + "validation_upgrade_frequency": 1, + "validation_upgrade_delay": 1 + } + } + } + } + } + }, + "parachains": [ + { + "bin": "/unique-chain/target/release/unique-collator", + "id": "2095", + "balance": "1000000000000000000000000", + "nodes": [ + { + "port": 31200, + "wsPort": 9944, + "rpcPort": 9933, + "name": "alice", + "flags": [ + "--unsafe-rpc-external", + "--unsafe-ws-external" + ] + } + ] + }, + { + "bin": "/acala/target/release/acala", + "id": "2000", + "chain": "karura-dev", + "balance": "1000000000000000000000", + "nodes": [ + { + "wsPort": 9946, + "port": 31202, + "name": "alice", + "flags": [ + "--unsafe-rpc-external", + "--unsafe-ws-external" + ] + } + ] + }, + { + "bin": "/moonbeam/target/release/moonbeam", + "id": 2023, + "balance": "1000000000000000000000", + "chain": "moonriver-local", + "chainInitializer": [ + "chainql", + "--tla-code=spec=import '${spec}'", + "minBondFix.jsonnet" + ], + "nodes": [ + { + "wsPort": 9947, + "port": 31203, + "name": "alice", + "flags": [ + "--unsafe-rpc-external", + "--unsafe-ws-external", + "--", + "--execution=wasm" + ] + } + ] + }, + { + "bin": "/cumulus/target/release/cumulus", + "id": "1000", + "chain": "statemine-local", + "balance": "1000000000000000000000000", + "nodes": [ + { + "wsPort": 9948, + "port": 31204, + "name": "alice", + "flags": [ + "--unsafe-rpc-external", + "--unsafe-ws-external" + ] + } + ] + } + ], + "simpleParachains": [], + "hrmpChannels": [ + { + "sender": 2095, + "recipient": 2000, + "maxCapacity": 8, + "maxMessageSize": 512 + }, + { + "sender": 2000, + "recipient": 2095, + "maxCapacity": 8, + "maxMessageSize": 512 + }, + { + "sender": 2095, + "recipient": 2023, + "maxCapacity": 8, + "maxMessageSize": 512 + }, + { + "sender": 2023, + "recipient": 2095, + "maxCapacity": 8, + "maxMessageSize": 512 + }, + { + "sender": 2095, + "recipient": 1000, + "maxCapacity": 8, + "maxMessageSize": 512 + }, + { + "sender": 1000, + "recipient": 2095, + "maxCapacity": 8, + "maxMessageSize": 512 + } + ], + "finalization": false +} + --- /dev/null +++ b/.docker/xcm-config/launch-config-xcm-unique-rococo.json @@ -0,0 +1,207 @@ +{ + "relaychain": { + "bin": "/polkadot/target/release/polkadot", + "chain": "rococo-local", + "chainInitializer": [ + "chainql", + "--tla-code=spec=import '${spec}'", + "5validators.jsonnet" + ], + "nodes": [ + { + "name": "alice", + "wsPort": 9844, + "rpcPort": 9843, + "port": 30444, + "flags": [ + "--unsafe-rpc-external", + "--unsafe-ws-external", + "-lparachain::candidate_validation=debug" + ] + }, + { + "name": "bob", + "wsPort": 9855, + "rpcPort": 9854, + "port": 30555, + "flags": [ + "--unsafe-rpc-external", + "--unsafe-ws-external", + "-lparachain::candidate_validation=debug" + ] + }, + { + "name": "charlie", + "wsPort": 9866, + "rpcPort": 9865, + "port": 30666, + "flags": [ + "--unsafe-rpc-external", + "--unsafe-ws-external", + "-lparachain::candidate_validation=debug" + ] + }, + { + "name": "dave", + "wsPort": 9877, + "rpcPort": 9876, + "port": 30777, + "flags": [ + "--unsafe-rpc-external", + "--unsafe-ws-external", + "-lparachain::candidate_validation=debug" + ] + }, + { + "name": "eve", + "wsPort": 9888, + "rpcPort": 9887, + "port": 30888, + "flags": [ + "--unsafe-rpc-external", + "--unsafe-ws-external", + "-lparachain::candidate_validation=debug" + ] + } + + ], + "genesis": { + "runtime": { + "runtime_genesis_config": { + "parachainsConfiguration": { + "config": { + "validation_upgrade_frequency": 1, + "validation_upgrade_delay": 1 + } + } + } + } + } + }, + "parachains": [ + { + "bin": "/unique-chain/target/release/unique-collator", + "id": "2037", + "balance": "1000000000000000000000000", + "nodes": [ + { + "port": 31200, + "wsPort": 9944, + "rpcPort": 9933, + "name": "alice", + "flags": [ + "-lruntime=trace", + "-lxcm=trace", + "--unsafe-rpc-external", + "--unsafe-ws-external" + ] + } + ] + }, + { + "bin": "/acala/target/release/acala", + "id": "2000", + "chain": "acala-dev", + "balance": "1000000000000000000000", + "chainInitializer": [ + "chainql", + "-e", + "(import '${spec}') {id+: '-local'}" + ], + "nodes": [ + { + "wsPort": 9946, + "port": 31202, + "name": "alice", + "flags": [ + "-lruntime=trace", + "-lxcm=trace", + "--unsafe-rpc-external", + "--unsafe-ws-external" + ] + } + ] + }, + { + "bin": "/moonbeam/target/release/moonbeam", + "id": "2004", + "balance": "1000000000000000000000", + "chain": "moonbeam-local", + "nodes": [ + { + "wsPort": 9947, + "port": 31203, + "name": "alice", + "flags": [ + "-lruntime=trace", + "-lxcm=trace", + "--unsafe-rpc-external", + "--unsafe-ws-external", + "--", + "--execution=wasm" + ] + } + ] + }, + { + "bin": "/cumulus/target/release/cumulus", + "id": "1000", + "chain": "statemint-local", + "balance": "1000000000000000000000000", + "nodes": [ + { + "wsPort": 9948, + "port": 31204, + "name": "alice", + "flags": [ + "-lruntime=trace", + "-lxcm=trace", + "--unsafe-rpc-external", + "--unsafe-ws-external" + ] + } + ] + } + ], + "simpleParachains": [], + "hrmpChannels": [ + { + "sender": 2037, + "recipient": 2000, + "maxCapacity": 8, + "maxMessageSize": 512 + }, + { + "sender": 2000, + "recipient": 2037, + "maxCapacity": 8, + "maxMessageSize": 512 + }, + { + "sender": 2037, + "recipient": 2004, + "maxCapacity": 8, + "maxMessageSize": 512 + }, + { + "sender": 2004, + "recipient": 2037, + "maxCapacity": 8, + "maxMessageSize": 512 + }, + { + "sender": 2037, + "recipient": 1000, + "maxCapacity": 8, + "maxMessageSize": 512 + }, + { + "sender": 1000, + "recipient": 2037, + "maxCapacity": 8, + "maxMessageSize": 512 + } + ], + "finalization": false +} + --- /dev/null +++ b/.docker/xcm-config/launch-config-xcm-unique.json @@ -0,0 +1,199 @@ +{ + "relaychain": { + "bin": "/polkadot/target/release/polkadot", + "chain": "westend-local", + "chainInitializer": [ + "chainql", + "--tla-code=spec=import '${spec}'", + "5validators.jsonnet" + ], + "nodes": [ + { + "name": "alice", + "wsPort": 9844, + "rpcPort": 9843, + "port": 30444, + "flags": [ + "--unsafe-rpc-external", + "--unsafe-ws-external", + "-lparachain::candidate_validation=debug" + ] + }, + { + "name": "bob", + "wsPort": 9855, + "rpcPort": 9854, + "port": 30555, + "flags": [ + "--unsafe-rpc-external", + "--unsafe-ws-external", + "-lparachain::candidate_validation=debug" + ] + }, + { + "name": "charlie", + "wsPort": 9866, + "rpcPort": 9865, + "port": 30666, + "flags": [ + "--unsafe-rpc-external", + "--unsafe-ws-external", + "-lparachain::candidate_validation=debug" + ] + }, + { + "name": "dave", + "wsPort": 9877, + "rpcPort": 9876, + "port": 30777, + "flags": [ + "--unsafe-rpc-external", + "--unsafe-ws-external", + "-lparachain::candidate_validation=debug" + ] + }, + { + "name": "eve", + "wsPort": 9888, + "rpcPort": 9887, + "port": 30888, + "flags": [ + "--unsafe-rpc-external", + "--unsafe-ws-external", + "-lparachain::candidate_validation=debug" + ] + } + + ], + "genesis": { + "runtime": { + "runtime_genesis_config": { + "parachainsConfiguration": { + "config": { + "validation_upgrade_frequency": 1, + "validation_upgrade_delay": 1 + } + } + } + } + } + }, + "parachains": [ + { + "bin": "/unique-chain/target/release/unique-collator", + "id": "2037", + "balance": "1000000000000000000000000", + "nodes": [ + { + "port": 31200, + "wsPort": 9944, + "rpcPort": 9933, + "name": "alice", + "flags": [ + "--unsafe-rpc-external", + "--unsafe-ws-external" + ] + } + ] + }, + { + "bin": "/acala/target/release/acala", + "id": "2000", + "chain": "acala-dev", + "balance": "1000000000000000000000", + "chainInitializer": [ + "chainql", + "-e", + "(import '${spec}') {id+: '-local'}" + ], + "nodes": [ + { + "wsPort": 9946, + "port": 31202, + "name": "alice", + "flags": [ + "--unsafe-rpc-external", + "--unsafe-ws-external" + ] + } + ] + }, + { + "bin": "/moonbeam/target/release/moonbeam", + "id": "2004", + "balance": "1000000000000000000000", + "chain": "moonbeam-local", + "nodes": [ + { + "wsPort": 9947, + "port": 31203, + "name": "alice", + "flags": [ + "--unsafe-rpc-external", + "--unsafe-ws-external", + "--", + "--execution=wasm" + ] + } + ] + }, + { + "bin": "/cumulus/target/release/cumulus", + "id": "1000", + "chain": "statemint-local", + "balance": "1000000000000000000000000", + "nodes": [ + { + "wsPort": 9948, + "port": 31204, + "name": "alice", + "flags": [ + "--unsafe-rpc-external", + "--unsafe-ws-external" + ] + } + ] + } + ], + "simpleParachains": [], + "hrmpChannels": [ + { + "sender": 2037, + "recipient": 2000, + "maxCapacity": 8, + "maxMessageSize": 512 + }, + { + "sender": 2000, + "recipient": 2037, + "maxCapacity": 8, + "maxMessageSize": 512 + }, + { + "sender": 2037, + "recipient": 2004, + "maxCapacity": 8, + "maxMessageSize": 512 + }, + { + "sender": 2004, + "recipient": 2037, + "maxCapacity": 8, + "maxMessageSize": 512 + }, + { + "sender": 2037, + "recipient": 1000, + "maxCapacity": 8, + "maxMessageSize": 512 + }, + { + "sender": 1000, + "recipient": 2037, + "maxCapacity": 8, + "maxMessageSize": 512 + } + ], + "finalization": false +} + --- /dev/null +++ b/.docker/xcm-config/minBondFix.jsonnet @@ -0,0 +1,10 @@ +function(spec) +spec { + genesis+: { + runtime+: { + parachainStaking+: { + candidates: std.map(function(candidate) [candidate[0], candidate[1] * 1000], super.candidates) + }, + }, + }, +} --- a/.env +++ b/.env @@ -12,3 +12,16 @@ OPAL_REPLICA_FROM=wss://eu-ws-opal.unique.network:443 QUARTZ_REPLICA_FROM=wss://eu-ws-quartz.unique.network:443 UNIQUE_REPLICA_FROM=wss://eu-ws.unique.network:443 + +POLKADOT_LAUNCH_BRANCH=feature/rewrite-chain-id-in-spec + +KARURA_BUILD_BRANCH=2.9.1 +ACALA_BUILD_BRANCH=2.9.2 + +MOONRIVER_BUILD_BRANCH=runtime-1701 +MOONBEAM_BUILD_BRANCH=runtime-1701 + +STATEMINE_BUILD_BRANCH=parachains-v9270 +STATEMINT_BUILD_BRANCH=release-parachains-v9230 +WESTMINT_BUILD_BRANCH=parachains-v9270 + --- a/.github/workflows/dev-build-tests_v2.yml +++ b/.github/workflows/dev-build-tests_v2.yml @@ -71,8 +71,8 @@ run: | yarn install yarn add mochawesome + node scripts/readyness.js echo "Ready to start tests" - node scripts/readyness.js yarn polkadot-types NOW=$(date +%s) && yarn test --reporter mochawesome --reporter-options reportFilename=test-${NOW} env: --- a/.github/workflows/market-test_v2.yml +++ b/.github/workflows/market-test_v2.yml @@ -142,7 +142,6 @@ with: path: qa-tests/ - - name: local-market:start run: docker-compose -f "qa-tests/.docker/docker-compose.market.yml" -f "qa-tests/.docker/docker-compose.${{ matrix.network }}.yml" up -d --build --- a/.github/workflows/try-runtime_v2.yml +++ b/.github/workflows/try-runtime_v2.yml @@ -1,7 +1,6 @@ on: workflow_call: - # A workflow run is made up of one or more jobs that can run sequentially or in parallel jobs: try-runtime: --- a/.github/workflows/xcm-testnet-build.yml +++ /dev/null @@ -1,151 +0,0 @@ -name: xcm-testnet-build - -# Controls when the action will run. -on: - workflow_call: - - # Allows you to run this workflow manually from the Actions tab - workflow_dispatch: - -#Define Workflow variables -env: - REPO_URL: ${{ github.server_url }}/${{ github.repository }} - -# A workflow run is made up of one or more jobs that can run sequentially or in parallel -jobs: - - prepare-execution-marix: - - name: Prepare execution matrix - - runs-on: [XL] - outputs: - matrix: ${{ steps.create_matrix.outputs.matrix }} - - steps: - - - name: Clean Workspace - uses: AutoModality/action-clean@v1.1.0 - - # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it - - uses: actions/checkout@v3 - with: - ref: ${{ github.head_ref }} #Checking out head commit - - - name: Read .env file - uses: xom9ikk/dotenv@v1.0.2 - - - name: Create Execution matrix - uses: fabiocaccamo/create-matrix-action@v2 - id: create_matrix - with: - matrix: | - network {opal}, runtime {opal}, features {opal-runtime}, acala_version {${{ env.ACALA_BUILD_BRANCH }}}, moonbeam_version {${{ env.MOONBEAM_BUILD_BRANCH }}}, cumulus_version {${{ env.WESTMINT_BUILD_BRANCH }}} - network {quartz}, runtime {quartz}, features {quartz-runtime}, acala_version {${{ env.KARURA_BUILD_BRANCH }}}, moonbeam_version {${{ env.MOONRIVER_BUILD_BRANCH }}}, cumulus_version {${{ env.STATEMINE_BUILD_BRANCH }}} - network {unique}, runtime {unique}, features {unique-runtime}, acala_version {${{ env.ACALA_BUILD_BRANCH }}}, moonbeam_version {${{ env.MOONBEAM_BUILD_BRANCH }}}, cumulus_version {${{ env.STATEMINT_BUILD_BRANCH }}} - - xcm-build: - - needs: prepare-execution-marix - # The type of runner that the job will run on - runs-on: [XL] - - timeout-minutes: 600 - - name: ${{ matrix.network }} - - continue-on-error: true #Do not stop testing of matrix runs failed. As it decided during PR review - it required 50/50& Let's check it with false. - - strategy: - matrix: - include: ${{fromJson(needs.prepare-execution-marix.outputs.matrix)}} - - steps: - - name: Skip if pull request is in Draft - if: github.event.pull_request.draft == true - run: exit 1 - - - name: Clean Workspace - uses: AutoModality/action-clean@v1.1.0 - - # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it - - uses: actions/checkout@v3 - with: - ref: ${{ github.head_ref }} #Checking out head commit - - - name: Read .env file - uses: xom9ikk/dotenv@v1.0.2 - - - name: Generate ENV related extend Dockerfile file - uses: cuchi/jinja2-action@v1.2.0 - with: - template: .docker/Dockerfile-xcm.j2 - output_file: .docker/Dockerfile-xcm.${{ matrix.network }}.yml - variables: | - RUST_TOOLCHAIN=${{ env.RUST_TOOLCHAIN }} - NETWORK=${{ matrix.network }} - POLKADOT_BUILD_BRANCH=${{ env.POLKADOT_BUILD_BRANCH }} - POLKADOT_LAUNCH_BRANCH=${{ env.POLKADOT_LAUNCH_BRANCH }} - FEATURE=${{ matrix.features }} - RUNTIME=${{ matrix.runtime }} - BRANCH=${{ github.head_ref }} - ACALA_BUILD_BRANCH=${{ matrix.acala_version }} - MOONBEAM_BUILD_BRANCH=${{ matrix.moonbeam_version }} - CUMULUS_BUILD_BRANCH=${{ matrix.cumulus_version }} - - - name: Show build Dockerfile - run: cat .docker/Dockerfile-xcm.${{ matrix.network }}.yml - - - name: Show launch-config-xcm-${{ matrix.network }} configuration - run: cat .docker/xcm-config/launch-config-xcm-${{ matrix.network }}.json - - - name: Run find-and-replace to remove slashes from branch name - uses: mad9000/actions-find-and-replace-string@2 - id: branchname - with: - source: ${{ github.head_ref }} - find: '/' - replace: '-' - - - name: Log in to Docker Hub - uses: docker/login-action@v2.0.0 - with: - username: ${{ secrets.CORE_DOCKERHUB_USERNAME }} - password: ${{ secrets.CORE_DOCKERHUB_TOKEN }} - - - name: Pull acala docker image - run: docker pull uniquenetwork/builder-acala:${{ matrix.acala_version }} - - - name: Pull moonbeam docker image - run: docker pull uniquenetwork/builder-moonbeam:${{ matrix.moonbeam_version }} - - - name: Pull cumulus docker image - run: docker pull uniquenetwork/builder-cumulus:${{ matrix.cumulus_version }} - - - name: Pull polkadot docker image - run: docker pull uniquenetwork/builder-polkadot:${{ env.POLKADOT_BUILD_BRANCH }} - - - name: Pull chainql docker image - run: docker pull uniquenetwork/builder-chainql:latest - - - name: Build the stack - run: cd .docker/ && docker build --no-cache --file ./Dockerfile-xcm.${{ matrix.network }}.yml --tag uniquenetwork/xcm-${{ matrix.network }}-testnet-local:nightly-${{ steps.branchname.outputs.value }}-${{ github.sha }} --tag uniquenetwork/xcm-${{ matrix.network }}-testnet-local:latest . - - - name: Push docker image version - run: docker push uniquenetwork/xcm-${{ matrix.network }}-testnet-local:nightly-${{ steps.branchname.outputs.value }}-${{ github.sha }} - - - name: Push docker image latest - run: docker push uniquenetwork/xcm-${{ matrix.network }}-testnet-local:latest - - - name: Clean Workspace - if: always() - uses: AutoModality/action-clean@v1.1.0 - - - name: Remove builder cache - if: always() # run this step always - run: | - docker builder prune -f - docker system prune -f - - - --- a/.github/workflows/xcm-tests_v2.yml +++ /dev/null @@ -1,175 +0,0 @@ -name: xcm-tests - -# Controls when the action will run. -on: - # Allows you to run this workflow manually from the Actions tab - workflow_call: - -#Define Workflow variables -env: - REPO_URL: ${{ github.server_url }}/${{ github.repository }} - - -# A workflow run is made up of one or more jobs that can run sequentially or in parallel -jobs: - - prepare-execution-marix: - - name: Prepare execution matrix - -# needs: [xcm-testnet-build] - - runs-on: XL - outputs: - matrix: ${{ steps.create_matrix.outputs.matrix }} - - steps: - - - name: Clean Workspace - uses: AutoModality/action-clean@v1.1.0 - - # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it - - uses: actions/checkout@v3 - with: - ref: ${{ github.head_ref }} #Checking out head commit - - - name: Read .env file - uses: xom9ikk/dotenv@v1.0.2 - - - name: Create Execution matrix - uses: fabiocaccamo/create-matrix-action@v2 - id: create_matrix - with: - matrix: | - network {opal}, runtime {opal}, features {opal-runtime}, runtest {testXcmOpal} - network {quartz}, runtime {quartz}, features {quartz-runtime}, runtest {testXcmQuartz} - network {unique}, runtime {unique}, features {unique-runtime}, runtest {testXcmUnique} - - xcm-tests: - needs: prepare-execution-marix - # The type of runner that the job will run on - runs-on: [XL] - - timeout-minutes: 600 - - name: ${{ matrix.network }} - - continue-on-error: true #Do not stop testing of matrix runs failed. As it decided during PR review - it required 50/50& Let's check it with false. - - strategy: - matrix: - include: ${{fromJson(needs.prepare-execution-marix.outputs.matrix)}} - - - steps: - - name: Skip if pull request is in Draft - if: github.event.pull_request.draft == true - run: exit 1 - - - name: Clean Workspace - uses: AutoModality/action-clean@v1.1.0 - - # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it - - uses: actions/checkout@v3 - with: - ref: ${{ github.head_ref }} #Checking out head commit - - - name: Read .env file - uses: xom9ikk/dotenv@v1.0.2 - - - name: Generate ENV related extend file for docker-compose - uses: cuchi/jinja2-action@v1.2.0 - with: - template: .docker/docker-compose.tmp-xcm-tests.j2 - output_file: .docker/docker-compose.xcm-tests.${{ matrix.network }}.yml - variables: | - NETWORK=${{ matrix.network }} - - - name: Show build configuration - run: cat .docker/docker-compose.xcm-tests.${{ matrix.network }}.yml - - - uses: actions/setup-node@v3 - with: - node-version: 16 - - - name: Build the stack - run: docker-compose -f ".docker/docker-compose.xcm-tests.${{ matrix.network }}.yml" up -d --remove-orphans --force-recreate --timeout 300 - - # 🚀 POLKADOT LAUNCH COMPLETE 🚀 - - name: Check if docker logs consist messages related to testing of xcm tests - if: success() - run: | - counter=160 - function check_container_status { - docker inspect -f {{.State.Running}} xcm-${{ matrix.network }}-testnet-local - } - function do_docker_logs { - docker logs --details xcm-${{ matrix.network }}-testnet-local 2>&1 - } - function is_started { - if [ "$(check_container_status)" == "true" ]; then - echo "Container: xcm-${{ matrix.network }}-testnet-local RUNNING"; - echo "Check Docker logs" - DOCKER_LOGS=$(do_docker_logs) - if [[ ${DOCKER_LOGS} = *"POLKADOT LAUNCH COMPLETE"* ]];then - echo "🚀 POLKADOT LAUNCH COMPLETE 🚀" - return 0 - else - echo "Message not found in logs output, repeating..." - return 1 - fi - else - echo "Container xcm-${{ matrix.network }}-testnet-local NOT RUNNING" - echo "Halting all future checks" - exit 1 - fi - echo "something goes wrong" - exit 1 - } - while ! is_started; do - echo "Waiting for special message in log files " - sleep 30s - counter=$(( $counter - 1 )) - echo "Counter: $counter" - if [ "$counter" -gt "0" ]; then - continue - else - break - fi - done - echo "Halting script" - exit 0 - shell: bash - - - name: Run XCM tests - working-directory: tests - run: | - yarn install - yarn add mochawesome - node scripts/readyness.js - echo "Ready to start tests" - NOW=$(date +%s) && yarn ${{ matrix.runtest }} --reporter mochawesome --reporter-options reportFilename=test-${NOW} - - - name: XCM Test Report - uses: phoenix-actions/test-reporting@v8 - id: test-report - if: success() || failure() # run this step even if previous step failed - with: - name: XCM Tests ${{ matrix.network }} # Name of the check run which will be created - path: tests/mochawesome-report/test-*.json # Path to test results - reporter: mochawesome-json - fail-on-error: 'false' - - - name: Stop running containers - if: always() # run this step always - run: docker-compose -f ".docker/docker-compose.xcm-tests.${{ matrix.network }}.yml" down - - - name: Clean Workspace - if: always() - uses: AutoModality/action-clean@v1.1.0 - - - name: Remove builder cache - if: always() # run this step always - run: | - docker system prune -a -f - --- a/.github/workflows/xcm.yml +++ b/.github/workflows/xcm.yml @@ -1,19 +1,400 @@ -name: Nesting XCM +name: xcm-testnet-build +# Controls when the action will run. on: workflow_call: + + # Allows you to run this workflow manually from the Actions tab + workflow_dispatch: +#Define Workflow variables +env: + REPO_URL: ${{ github.server_url }}/${{ github.repository }} +# A workflow run is made up of one or more jobs that can run sequentially or in parallel jobs: - xcm-testnet-build: - name: testnet build - uses: ./.github/workflows/xcm-testnet-build.yml - secrets: inherit + prepare-execution-marix: + + name: Prepare execution matrix + + runs-on: [XL] + outputs: + matrix: ${{ steps.create_matrix.outputs.matrix }} + + steps: + + - name: Clean Workspace + uses: AutoModality/action-clean@v1.1.0 + + # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it + - uses: actions/checkout@v3 + with: + ref: ${{ github.head_ref }} #Checking out head commit + + - name: Read .env file + uses: xom9ikk/dotenv@v1.0.2 + + - name: Create Execution matrix + uses: fabiocaccamo/create-matrix-action@v2 + id: create_matrix + with: + matrix: | + network {opal}, runtime {opal}, features {opal-runtime}, acala_version {${{ env.ACALA_BUILD_BRANCH }}}, moonbeam_version {${{ env.MOONBEAM_BUILD_BRANCH }}}, cumulus_version {${{ env.WESTMINT_BUILD_BRANCH }}}, runtest {testXcmOpal} + network {quartz}, runtime {quartz}, features {quartz-runtime}, acala_version {${{ env.KARURA_BUILD_BRANCH }}}, moonbeam_version {${{ env.MOONRIVER_BUILD_BRANCH }}}, cumulus_version {${{ env.STATEMINE_BUILD_BRANCH }}}, runtest {testXcmQuartz} + network {unique}, runtime {unique}, features {unique-runtime}, acala_version {${{ env.ACALA_BUILD_BRANCH }}}, moonbeam_version {${{ env.MOONBEAM_BUILD_BRANCH }}}, cumulus_version {${{ env.STATEMINT_BUILD_BRANCH }}}, runtest {testXcmUnique} + + xcm-build: + + needs: prepare-execution-marix + # The type of runner that the job will run on + runs-on: [XL] + + timeout-minutes: 600 + + name: ${{ matrix.network }} + + continue-on-error: true #Do not stop testing of matrix runs failed. As it decided during PR review - it required 50/50& Let's check it with false. + + strategy: + matrix: + include: ${{fromJson(needs.prepare-execution-marix.outputs.matrix)}} + + steps: + - name: Skip if pull request is in Draft + if: github.event.pull_request.draft == true + run: exit 1 + + - name: Clean Workspace + uses: AutoModality/action-clean@v1.1.0 + + # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it + - uses: actions/checkout@v3 + with: + ref: ${{ github.head_ref }} #Checking out head commit + + - name: Read .env file + uses: xom9ikk/dotenv@v1.0.2 + + - name: Log in to Docker Hub + uses: docker/login-action@v2.0.0 + with: + username: ${{ secrets.CORE_DOCKERHUB_USERNAME }} + password: ${{ secrets.CORE_DOCKERHUB_TOKEN }} + + - name: Install jq + run: sudo apt install jq -y + + # Check POLKADOT version and build it if it doesn't exist in repository + - name: Generate ENV related extend Dockerfile file for POLKADOT + uses: cuchi/jinja2-action@v1.2.0 + with: + template: .docker/Dockerfile-polkadot.j2 + output_file: .docker/Dockerfile-polkadot.${{ env.POLKADOT_BUILD_BRANCH }}.yml + variables: | + RUST_TOOLCHAIN=${{ env.RUST_TOOLCHAIN }} + POLKADOT_BUILD_BRANCH=${{ env.POLKADOT_BUILD_BRANCH }} + + - name: Check if the dockerhub repository contains the needed version POLKADOT + run: | + # aquire token + TOKEN=$(curl -s -H "Content-Type: application/json" -X POST -d '{"username": "'${{ secrets.CORE_DOCKERHUB_USERNAME }}'", "password": "'${{ secrets.CORE_DOCKERHUB_TOKEN }}'"}' https://hub.docker.com/v2/users/login/ | jq -r .token) + export TOKEN=$TOKEN + # Get TAGS from DOCKERHUB POLKADOT repository + POLKADOT_TAGS=$(curl -s -H "Authorization: JWT ${TOKEN}" https://hub.docker.com/v2/repositories/uniquenetwork/builder-polkadot/tags/?page_size=100 | jq -r '."results"[]["name"]') + # Show TAGS + echo "POLKADOT TAGS:" + echo $POLKADOT_TAGS + # Check correct version POLKADOT and build it if it doesn't exist in POLKADOT TAGS + if [[ ${POLKADOT_TAGS[*]} =~ (^|[[:space:]])"${{ env.POLKADOT_BUILD_BRANCH }}"($|[[:space:]]) ]]; then + echo "Repository has needed POLKADOT version"; + docker pull uniquenetwork/builder-polkadot:${{ env.POLKADOT_BUILD_BRANCH }} + else + echo "Repository has not needed POLKADOT version, so build it"; + cd .docker/ && docker build --no-cache --file ./Dockerfile-polkadot.${{ env.POLKADOT_BUILD_BRANCH }}.yml --tag uniquenetwork/builder-polkadot:${{ env.POLKADOT_BUILD_BRANCH }} . + echo "Push needed POLKADOT version to the repository"; + docker push uniquenetwork/builder-polkadot:${{ env.POLKADOT_BUILD_BRANCH }} + fi + shell: bash + + # Check ACALA version and build it if it doesn't exist in repository + - name: Generate ENV related extend Dockerfile file for ACALA + uses: cuchi/jinja2-action@v1.2.0 + with: + template: .docker/Dockerfile-acala.j2 + output_file: .docker/Dockerfile-acala.${{ matrix.acala_version }}.yml + variables: | + RUST_TOOLCHAIN=${{ env.RUST_TOOLCHAIN }} + ACALA_BUILD_BRANCH=${{ matrix.acala_version }} + + - name: Check if the dockerhub repository contains the needed ACALA version + run: | + # aquire token + TOKEN=$(curl -s -H "Content-Type: application/json" -X POST -d '{"username": "'${{ secrets.CORE_DOCKERHUB_USERNAME }}'", "password": "'${{ secrets.CORE_DOCKERHUB_TOKEN }}'"}' https://hub.docker.com/v2/users/login/ | jq -r .token) + export TOKEN=$TOKEN + + # Get TAGS from DOCKERHUB repository + ACALA_TAGS=$(curl -s -H "Authorization: JWT ${TOKEN}" https://hub.docker.com/v2/repositories/uniquenetwork/builder-acala/tags/?page_size=100 | jq -r '."results"[]["name"]') + # Show TAGS + echo "ACALA TAGS:" + echo $ACALA_TAGS + # Check correct version ACALA and build it if it doesn't exist in ACALA TAGS + if [[ ${ACALA_TAGS[*]} =~ (^|[[:space:]])"${{ matrix.acala_version }}"($|[[:space:]]) ]]; then + echo "Repository has needed ACALA version"; + docker pull uniquenetwork/builder-acala:${{ matrix.acala_version }} + else + echo "Repository has not needed ACALA version, so build it"; + cd .docker/ && docker build --no-cache --file ./Dockerfile-acala.${{ matrix.acala_version }}.yml --tag uniquenetwork/builder-acala:${{ matrix.acala_version }} . + echo "Push needed ACALA version to the repository"; + docker push uniquenetwork/builder-acala:${{ matrix.acala_version }} + fi + shell: bash + + # Check MOONBEAM version and build it if it doesn't exist in repository + - name: Generate ENV related extend Dockerfile file for MOONBEAM + uses: cuchi/jinja2-action@v1.2.0 + with: + template: .docker/Dockerfile-moonbeam.j2 + output_file: .docker/Dockerfile-moonbeam.${{ matrix.moonbeam_version }}.yml + variables: | + RUST_TOOLCHAIN=${{ env.RUST_TOOLCHAIN }} + MOONBEAM_BUILD_BRANCH=${{ matrix.moonbeam_version }} + + - name: Check if the dockerhub repository contains the needed MOONBEAM version + run: | + # aquire token + TOKEN=$(curl -s -H "Content-Type: application/json" -X POST -d '{"username": "'${{ secrets.CORE_DOCKERHUB_USERNAME }}'", "password": "'${{ secrets.CORE_DOCKERHUB_TOKEN }}'"}' https://hub.docker.com/v2/users/login/ | jq -r .token) + export TOKEN=$TOKEN + + # Get TAGS from DOCKERHUB repository + MOONBEAM_TAGS=$(curl -s -H "Authorization: JWT ${TOKEN}" https://hub.docker.com/v2/repositories/uniquenetwork/builder-moonbeam/tags/?page_size=100 | jq -r '."results"[]["name"]') + # Show TAGS + echo "MOONBEAM TAGS:" + echo $MOONBEAM_TAGS + # Check correct version MOONBEAM and build it if it doesn't exist in MOONBEAM TAGS + if [[ ${MOONBEAM_TAGS[*]} =~ (^|[[:space:]])"${{ matrix.moonbeam_version }}"($|[[:space:]]) ]]; then + echo "Repository has needed MOONBEAM version"; + docker pull uniquenetwork/builder-moonbeam:${{ matrix.moonbeam_version }} + else + echo "Repository has not needed MOONBEAM version, so build it"; + cd .docker/ && docker build --no-cache --file ./Dockerfile-moonbeam.${{ matrix.moonbeam_version }}.yml --tag uniquenetwork/builder-moonbeam:${{ matrix.moonbeam_version }} . + echo "Push needed MOONBEAM version to the repository"; + docker push uniquenetwork/builder-moonbeam:${{ matrix.moonbeam_version }} + fi + shell: bash + + + # Check CUMULUS version and build it if it doesn't exist in repository + - name: Generate ENV related extend Dockerfile file for CUMULUS + uses: cuchi/jinja2-action@v1.2.0 + with: + template: .docker/Dockerfile-cumulus.j2 + output_file: .docker/Dockerfile-cumulus.${{ matrix.cumulus_version }}.yml + variables: | + RUST_TOOLCHAIN=${{ env.RUST_TOOLCHAIN }} + CUMULUS_BUILD_BRANCH=${{ matrix.cumulus_version }} + + - name: Check if the dockerhub repository contains the needed CUMULUS version + run: | + # aquire token + TOKEN=$(curl -s -H "Content-Type: application/json" -X POST -d '{"username": "'${{ secrets.CORE_DOCKERHUB_USERNAME }}'", "password": "'${{ secrets.CORE_DOCKERHUB_TOKEN }}'"}' https://hub.docker.com/v2/users/login/ | jq -r .token) + export TOKEN=$TOKEN + + # Get TAGS from DOCKERHUB repository + CUMULUS_TAGS=$(curl -s -H "Authorization: JWT ${TOKEN}" https://hub.docker.com/v2/repositories/uniquenetwork/builder-cumulus/tags/?page_size=100 | jq -r '."results"[]["name"]') + # Show TAGS + echo "CUMULUS TAGS:" + echo $CUMULUS_TAGS + # Check correct version CUMULUS and build it if it doesn't exist in CUMULUS TAGS + if [[ ${CUMULUS_TAGS[*]} =~ (^|[[:space:]])"${{ matrix.cumulus_version }}"($|[[:space:]]) ]]; then + echo "Repository has needed CUMULUS version"; + docker pull uniquenetwork/builder-cumulus:${{ matrix.cumulus_version }} + else + echo "Repository has not needed CUMULUS version, so build it"; + cd .docker/ && docker build --no-cache --file ./Dockerfile-cumulus.${{ matrix.cumulus_version }}.yml --tag uniquenetwork/builder-cumulus:${{ matrix.cumulus_version }} . + echo "Push needed CUMULUS version to the repository"; + docker push uniquenetwork/builder-cumulus:${{ matrix.cumulus_version }} + fi + shell: bash + + + # Build main image for XCM + - name: Generate ENV related extend Dockerfile file + uses: cuchi/jinja2-action@v1.2.0 + with: + template: .docker/Dockerfile-xcm.j2 + output_file: .docker/Dockerfile-xcm.${{ matrix.network }}.yml + variables: | + RUST_TOOLCHAIN=${{ env.RUST_TOOLCHAIN }} + NETWORK=${{ matrix.network }} + POLKADOT_BUILD_BRANCH=${{ env.POLKADOT_BUILD_BRANCH }} + POLKADOT_LAUNCH_BRANCH=${{ env.POLKADOT_LAUNCH_BRANCH }} + FEATURE=${{ matrix.features }} + RUNTIME=${{ matrix.runtime }} + BRANCH=${{ github.head_ref }} + ACALA_BUILD_BRANCH=${{ matrix.acala_version }} + MOONBEAM_BUILD_BRANCH=${{ matrix.moonbeam_version }} + CUMULUS_BUILD_BRANCH=${{ matrix.cumulus_version }} + + - name: Show build Dockerfile + run: cat .docker/Dockerfile-xcm.${{ matrix.network }}.yml + + - name: Show launch-config-xcm-${{ matrix.network }} configuration + run: cat .docker/xcm-config/launch-config-xcm-${{ matrix.network }}.json + + - name: Run find-and-replace to remove slashes from branch name + uses: mad9000/actions-find-and-replace-string@2 + id: branchname + with: + source: ${{ github.head_ref }} + find: '/' + replace: '-' + + - name: Pull chainql docker image + run: docker pull uniquenetwork/builder-chainql:latest + + - name: Build the stack + run: cd .docker/ && docker build --no-cache --file ./Dockerfile-xcm.${{ matrix.network }}.yml --tag uniquenetwork/xcm-${{ matrix.network }}-testnet-local:nightly-${{ steps.branchname.outputs.value }}-${{ github.sha }} --tag uniquenetwork/xcm-${{ matrix.network }}-testnet-local:latest . + + - name: Push docker image version + run: docker push uniquenetwork/xcm-${{ matrix.network }}-testnet-local:nightly-${{ steps.branchname.outputs.value }}-${{ github.sha }} + + - name: Push docker image latest + run: docker push uniquenetwork/xcm-${{ matrix.network }}-testnet-local:latest + + - name: Remove builder cache + if: always() # run this step always + run: | + docker builder prune -f + docker system prune -f + xcm-tests: - name: tests - needs: [ xcm-testnet-build ] - uses: ./.github/workflows/xcm-tests_v2.yml + needs: [prepare-execution-marix, xcm-build] + # The type of runner that the job will run on + runs-on: [XL] + + timeout-minutes: 600 + + name: ${{ matrix.network }} + + continue-on-error: true #Do not stop testing of matrix runs failed. As it decided during PR review - it required 50/50& Let's check it with false. + + strategy: + matrix: + include: ${{fromJson(needs.prepare-execution-marix.outputs.matrix)}} + + steps: + - name: Skip if pull request is in Draft + if: github.event.pull_request.draft == true + run: exit 1 + + - name: Clean Workspace + uses: AutoModality/action-clean@v1.1.0 + + # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it + - uses: actions/checkout@v3 + with: + ref: ${{ github.head_ref }} #Checking out head commit + + - name: Read .env file + uses: xom9ikk/dotenv@v1.0.2 + + - name: Generate ENV related extend file for docker-compose + uses: cuchi/jinja2-action@v1.2.0 + with: + template: .docker/docker-compose.tmp-xcm-tests.j2 + output_file: .docker/docker-compose.xcm-tests.${{ matrix.network }}.yml + variables: | + NETWORK=${{ matrix.network }} + - name: Show build configuration + run: cat .docker/docker-compose.xcm-tests.${{ matrix.network }}.yml + - uses: actions/setup-node@v3 + with: + node-version: 16 + + - name: Build the stack + run: docker-compose -f ".docker/docker-compose.xcm-tests.${{ matrix.network }}.yml" up -d --remove-orphans --force-recreate --timeout 300 + + # 🚀 POLKADOT LAUNCH COMPLETE 🚀 + - name: Check if docker logs consist messages related to testing of xcm tests + if: success() + run: | + counter=160 + function check_container_status { + docker inspect -f {{.State.Running}} xcm-${{ matrix.network }}-testnet-local + } + function do_docker_logs { + docker logs --details xcm-${{ matrix.network }}-testnet-local 2>&1 + } + function is_started { + if [ "$(check_container_status)" == "true" ]; then + echo "Container: xcm-${{ matrix.network }}-testnet-local RUNNING"; + echo "Check Docker logs" + DOCKER_LOGS=$(do_docker_logs) + if [[ ${DOCKER_LOGS} = *"POLKADOT LAUNCH COMPLETE"* ]];then + echo "🚀 POLKADOT LAUNCH COMPLETE 🚀" + return 0 + else + echo "Message not found in logs output, repeating..." + return 1 + fi + else + echo "Container xcm-${{ matrix.network }}-testnet-local NOT RUNNING" + echo "Halting all future checks" + exit 1 + fi + echo "something goes wrong" + exit 1 + } + while ! is_started; do + echo "Waiting for special message in log files " + sleep 30s + counter=$(( $counter - 1 )) + echo "Counter: $counter" + if [ "$counter" -gt "0" ]; then + continue + else + break + fi + done + echo "Halting script" + exit 0 + shell: bash + + - name: Run XCM tests + working-directory: tests + run: | + yarn install + yarn add mochawesome + node scripts/readyness.js + echo "Ready to start tests" + yarn polkadot-types + NOW=$(date +%s) && yarn ${{ matrix.runtest }} --reporter mochawesome --reporter-options reportFilename=test-${NOW} + env: + RPC_URL: http://127.0.0.1:9933/ + + - name: XCM Test Report + uses: phoenix-actions/test-reporting@v8 + id: test-report + if: success() || failure() # run this step even if previous step failed + with: + name: XCM Tests ${{ matrix.network }} # Name of the check run which will be created + path: tests/mochawesome-report/test-*.json # Path to test results + reporter: mochawesome-json + fail-on-error: 'false' + + - name: Stop running containers + if: always() # run this step always + run: docker-compose -f ".docker/docker-compose.xcm-tests.${{ matrix.network }}.yml" down + + - name: Clean Workspace + if: always() + uses: AutoModality/action-clean@v1.1.0 + + - name: Remove builder cache + if: always() # run this step always + run: | + docker system prune -a -f --- a/Cargo.lock +++ b/Cargo.lock @@ -697,6 +697,26 @@ ] [[package]] +name = "bondrewd" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d1660fac8d3acced44dac64453fafedf5aab2de196b932c727e63e4ae42d1cc" +dependencies = [ + "bondrewd-derive", +] + +[[package]] +name = "bondrewd-derive" +version = "0.3.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "723da0dee1eef38edc021b0793f892bdc024500c6a5b0727a2efe16f0e0a6977" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] name = "bounded-vec" version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -4586,6 +4606,16 @@ ] [[package]] +name = "logtest" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb3e43a8657c1d64516dcc9db8ca03826a4aceaf89d5ce1b37b59f6ff0e43026" +dependencies = [ + "lazy_static", + "log", +] + +[[package]] name = "lru" version = "0.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -5163,8 +5193,13 @@ "frame-system-rpc-runtime-api", "frame-try-runtime", "hex-literal", + "impl-trait-for-tuples", "log", + "logtest", + "orml-tokens", + "orml-traits", "orml-vesting", + "orml-xtokens", "pallet-app-promotion", "pallet-aura", "pallet-balances", @@ -5177,6 +5212,7 @@ "pallet-evm-contract-helpers", "pallet-evm-migration", "pallet-evm-transaction-payment", + "pallet-foreign-assets", "pallet-fungible", "pallet-inflation", "pallet-nonfungible", @@ -5282,6 +5318,53 @@ ] [[package]] +name = "orml-tokens" +version = "0.4.1-dev" +source = "git+https://github.com/open-web3-stack/open-runtime-module-library?branch=polkadot-v0.9.27#377213f750755cc48e80a3131eaae63b5eda8362" +dependencies = [ + "frame-support", + "frame-system", + "orml-traits", + "parity-scale-codec 3.1.5", + "scale-info", + "serde", + "sp-runtime", + "sp-std", +] + +[[package]] +name = "orml-traits" +version = "0.4.1-dev" +source = "git+https://github.com/open-web3-stack/open-runtime-module-library?branch=polkadot-v0.9.27#377213f750755cc48e80a3131eaae63b5eda8362" +dependencies = [ + "frame-support", + "impl-trait-for-tuples", + "num-traits", + "orml-utilities", + "parity-scale-codec 3.1.5", + "scale-info", + "serde", + "sp-io", + "sp-runtime", + "sp-std", + "xcm", +] + +[[package]] +name = "orml-utilities" +version = "0.4.1-dev" +source = "git+https://github.com/open-web3-stack/open-runtime-module-library?branch=polkadot-v0.9.27#377213f750755cc48e80a3131eaae63b5eda8362" +dependencies = [ + "frame-support", + "parity-scale-codec 3.1.5", + "scale-info", + "serde", + "sp-io", + "sp-runtime", + "sp-std", +] + +[[package]] name = "orml-vesting" version = "0.4.1-dev" source = "git+https://github.com/open-web3-stack/open-runtime-module-library?branch=polkadot-v0.9.27#377213f750755cc48e80a3131eaae63b5eda8362" @@ -5297,6 +5380,41 @@ ] [[package]] +name = "orml-xcm-support" +version = "0.4.1-dev" +source = "git+https://github.com/open-web3-stack/open-runtime-module-library?branch=polkadot-v0.9.27#377213f750755cc48e80a3131eaae63b5eda8362" +dependencies = [ + "frame-support", + "orml-traits", + "parity-scale-codec 3.1.5", + "sp-runtime", + "sp-std", + "xcm", + "xcm-executor", +] + +[[package]] +name = "orml-xtokens" +version = "0.4.1-dev" +source = "git+https://github.com/open-web3-stack/open-runtime-module-library?branch=polkadot-v0.9.27#377213f750755cc48e80a3131eaae63b5eda8362" +dependencies = [ + "cumulus-primitives-core", + "frame-support", + "frame-system", + "orml-traits", + "orml-xcm-support", + "pallet-xcm", + "parity-scale-codec 3.1.5", + "scale-info", + "serde", + "sp-io", + "sp-runtime", + "sp-std", + "xcm", + "xcm-executor", +] + +[[package]] name = "os_str_bytes" version = "6.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -5791,6 +5909,34 @@ ] [[package]] +name = "pallet-foreign-assets" +version = "0.1.0" +dependencies = [ + "frame-benchmarking", + "frame-support", + "frame-system", + "hex", + "log", + "orml-tokens", + "pallet-balances", + "pallet-common", + "pallet-fungible", + "pallet-timestamp", + "parity-scale-codec 3.1.5", + "scale-info", + "serde", + "serde_json", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", + "up-data-structs", + "xcm", + "xcm-builder", + "xcm-executor", +] + +[[package]] name = "pallet-fungible" version = "0.1.5" dependencies = [ @@ -8397,8 +8543,13 @@ "frame-system-rpc-runtime-api", "frame-try-runtime", "hex-literal", + "impl-trait-for-tuples", "log", + "logtest", + "orml-tokens", + "orml-traits", "orml-vesting", + "orml-xtokens", "pallet-app-promotion", "pallet-aura", "pallet-balances", @@ -8411,6 +8562,7 @@ "pallet-evm-contract-helpers", "pallet-evm-migration", "pallet-evm-transaction-payment", + "pallet-foreign-assets", "pallet-fungible", "pallet-inflation", "pallet-nonfungible", @@ -12134,7 +12286,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "97fee6b57c6a41524a810daee9286c02d7752c4253064d0b05472833a438f675" dependencies = [ - "cfg-if 0.1.10", + "cfg-if 1.0.0", "digest 0.10.3", "rand 0.8.5", "static_assertions", @@ -12391,8 +12543,13 @@ "frame-system-rpc-runtime-api", "frame-try-runtime", "hex-literal", + "impl-trait-for-tuples", "log", + "logtest", + "orml-tokens", + "orml-traits", "orml-vesting", + "orml-xtokens", "pallet-app-promotion", "pallet-aura", "pallet-balances", @@ -12405,6 +12562,7 @@ "pallet-evm-contract-helpers", "pallet-evm-migration", "pallet-evm-transaction-payment", + "pallet-foreign-assets", "pallet-fungible", "pallet-inflation", "pallet-nonfungible", @@ -12497,6 +12655,7 @@ name = "up-data-structs" version = "0.2.2" dependencies = [ + "bondrewd", "derivative", "frame-support", "frame-system", --- a/Cargo.toml +++ b/Cargo.toml @@ -6,9 +6,12 @@ 'client/*', 'primitives/*', 'crates/*', + 'runtime/opal', + 'runtime/quartz', + 'runtime/unique', 'runtime/tests', ] -exclude = ["runtime/unique", "runtime/quartz"] +default-members = ['node/*', 'runtime/opal'] [profile.release] panic = 'unwind' --- a/Makefile +++ b/Makefile @@ -128,9 +128,13 @@ bench-rmrk-equip: make _bench PALLET=proxy-rmrk-equip +.PHONY: bench-foreign-assets +bench-foreign-assets: + make _bench PALLET=foreign-assets + .PHONY: bench-app-promotion bench-app-promotion: make _bench PALLET=app-promotion PALLET_DIR=app-promotion .PHONY: bench -bench: bench-evm-migration bench-unique bench-structure bench-fungible bench-refungible bench-nonfungible bench-scheduler bench-rmrk-core bench-rmrk-equip +bench: bench-evm-migration bench-unique bench-structure bench-fungible bench-refungible bench-nonfungible bench-scheduler bench-rmrk-core bench-rmrk-equip bench-foreign-assets --- a/README.md +++ b/README.md @@ -195,7 +195,7 @@ xtokens -> transfer currencyId: - ForeingAsset + ForeignAsset amount: --- a/node/cli/Cargo.toml +++ b/node/cli/Cargo.toml @@ -302,7 +302,7 @@ [dependencies] futures = '0.3.17' -log = '0.4.14' +log = '0.4.16' flexi_logger = "0.22.5" parking_lot = '0.12.1' clap = "3.1.2" --- a/node/cli/src/chain_spec.rs +++ b/node/cli/src/chain_spec.rs @@ -65,6 +65,14 @@ Unknown(String), } +#[cfg(not(feature = "unique-runtime"))] +/// PARA_ID for Opal/Quartz +const PARA_ID: u32 = 2095; + +#[cfg(feature = "unique-runtime")] +/// PARA_ID for Unique +const PARA_ID: u32 = 2037; + pub trait RuntimeIdentification { fn runtime_id(&self) -> RuntimeId; } @@ -167,6 +175,7 @@ .collect(), }, treasury: Default::default(), + tokens: TokensConfig { balances: vec![] }, sudo: SudoConfig { key: Some($root_key), }, @@ -235,7 +244,7 @@ get_account_id_from_seed::("Eve//stash"), get_account_id_from_seed::("Ferdie//stash"), ], - 1000 + PARA_ID ) }, // Bootnodes @@ -250,7 +259,7 @@ // Extensions Extensions { relay_chain: "rococo-dev".into(), - para_id: 1000, + para_id: PARA_ID, }, ) } @@ -303,7 +312,7 @@ get_account_id_from_seed::("Eve//stash"), get_account_id_from_seed::("Ferdie//stash"), ], - 1000 + PARA_ID ) }, // Bootnodes @@ -318,7 +327,7 @@ // Extensions Extensions { relay_chain: "westend-local".into(), - para_id: 1000, + para_id: PARA_ID, }, ) } --- a/pallets/app-promotion/src/benchmarking.rs +++ b/pallets/app-promotion/src/benchmarking.rs @@ -20,11 +20,10 @@ use crate::Pallet as PromototionPallet; use sp_runtime::traits::Bounded; -use sp_std::vec; use frame_benchmarking::{benchmarks, account}; use frame_support::traits::OnInitialize; -use frame_system::{Origin, RawOrigin}; +use frame_system::RawOrigin; use pallet_unique::benchmarking::create_nft_collection; use pallet_evm_migration::Pallet as EvmMigrationPallet; --- a/pallets/common/src/benchmarking.rs +++ b/pallets/common/src/benchmarking.rs @@ -19,8 +19,8 @@ use pallet_evm::account::CrossAccountId; use frame_benchmarking::{benchmarks, account}; use up_data_structs::{ - CollectionMode, CreateCollectionData, CollectionId, Property, PropertyKey, PropertyValue, - CollectionPermissions, NestingPermissions, MAX_COLLECTION_NAME_LENGTH, + CollectionMode, CollectionFlags, CreateCollectionData, CollectionId, Property, PropertyKey, + PropertyValue, CollectionPermissions, NestingPermissions, MAX_COLLECTION_NAME_LENGTH, MAX_COLLECTION_DESCRIPTION_LENGTH, MAX_TOKEN_PREFIX_LENGTH, MAX_PROPERTIES_PER_ITEM, }; use frame_support::{ @@ -116,7 +116,7 @@ create_collection_raw( owner, CollectionMode::NFT, - |owner, data| >::init_collection(owner, data, true), + |owner, data| >::init_collection(owner, data, CollectionFlags::default()), |h| h, ) } --- a/pallets/common/src/lib.rs +++ b/pallets/common/src/lib.rs @@ -70,6 +70,7 @@ COLLECTION_NUMBER_LIMIT, Collection, RpcCollection, + CollectionFlags, CollectionId, CreateItemData, MAX_TOKEN_PREFIX_LENGTH, @@ -252,9 +253,9 @@ } /// Checks that the collection was created with, and must be operated upon through **Unique API**. - /// Now check only the `external_collection` flag and if it's **true**, then return [`Error::CollectionIsExternal`] error. + /// Now check only the `external` flag and if it's **true**, then return [`Error::CollectionIsExternal`] error. pub fn check_is_internal(&self) -> DispatchResult { - if self.external_collection { + if self.flags.external { return Err(>::CollectionIsExternal)?; } @@ -262,9 +263,9 @@ } /// Checks that the collection was created with, and must be operated upon through an **assimilated API**. - /// Now check only the `external_collection` flag and if it's **false**, then return [`Error::CollectionIsInternal`] error. + /// Now check only the `external` flag and if it's **false**, then return [`Error::CollectionIsInternal`] error. pub fn check_is_external(&self) -> DispatchResult { - if !self.external_collection { + if !self.flags.external { return Err(>::CollectionIsInternal)?; } @@ -792,7 +793,7 @@ sponsorship, limits, permissions, - external_collection, + flags, } = >::get(collection)?; let token_property_permissions = >::get(collection) @@ -822,7 +823,8 @@ permissions, token_property_permissions, properties, - read_only: external_collection, + read_only: flags.external, + foreign: flags.foreign, }) } } @@ -861,11 +863,11 @@ /// /// * `owner` - The owner of the collection. /// * `data` - Description of the created collection. - /// * `is_external` - Marks that collection managet by not "Unique network". + /// * `flags` - Extra flags to store. pub fn init_collection( owner: T::CrossAccountId, data: CreateCollectionData, - is_external: bool, + flags: CollectionFlags, ) -> Result { { ensure!( @@ -909,7 +911,7 @@ Self::clamp_permissions(data.mode.clone(), &Default::default(), permissions) }) .unwrap_or_else(|| Ok(CollectionPermissions::default()))?, - external_collection: is_external, + flags, }; let mut collection_properties = up_data_structs::CollectionProperties::get(); --- /dev/null +++ b/pallets/foreign-assets/Cargo.toml @@ -0,0 +1,53 @@ +[package] +name = "pallet-foreign-assets" +version = "0.1.0" +license = "GPLv3" +edition = "2021" + +[dependencies] +log = { version = "0.4.16", default-features = false } +serde = { version = "1.0.136", optional = true } +scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false } +sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27", default-features = false } +sp-std = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27", default-features = false } +frame-support = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27", default-features = false } +frame-system = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27", default-features = false } +up-data-structs = { default-features = false, path = '../../primitives/data-structs' } +pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27", default-features = false } +pallet-common = { default-features = false, path = '../common' } +pallet-fungible = { default-features = false, path = '../fungible' } +xcm = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.27", default-features = false } +xcm-builder = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.27", default-features = false } +xcm-executor = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.27", default-features = false } +#orml-tokens = { git = 'https://github.com/UniqueNetwork/open-runtime-module-library', branch = 'unique-polkadot-v0.9.24', version = "0.4.1-dev", default-features = false } +orml-tokens = { git = "https://github.com/open-web3-stack/open-runtime-module-library", branch = "polkadot-v0.9.27", version = "0.4.1-dev", default-features = false } +frame-benchmarking = { default-features = false, optional = true, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" } + +[dev-dependencies] +serde_json = "1.0.68" +hex = { version = "0.4" } +sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" } +sp-io = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" } +pallet-timestamp = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" } +pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" } + +[features] +default = ["std"] +std = [ + "serde", + "log/std", + "codec/std", + "scale-info/std", + "sp-runtime/std", + "sp-std/std", + "frame-support/std", + "frame-system/std", + "up-data-structs/std", + "pallet-common/std", + "pallet-balances/std", + "pallet-fungible/std", + "orml-tokens/std" +] +try-runtime = ["frame-support/try-runtime"] +runtime-benchmarks = ['frame-benchmarking', 'pallet-common/runtime-benchmarks'] \ No newline at end of file --- /dev/null +++ b/pallets/foreign-assets/src/benchmarking.rs @@ -0,0 +1,68 @@ +// 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 . + +#![allow(missing_docs)] + +use super::{Config, Pallet, Call}; +use frame_benchmarking::{benchmarks, account}; +use frame_system::RawOrigin; +use crate::AssetMetadata; +use xcm::opaque::latest::Junction::Parachain; +use xcm::VersionedMultiLocation; +use frame_support::{ + traits::{Currency}, +}; +use sp_std::boxed::Box; + +benchmarks! { + register_foreign_asset { + let owner: T::AccountId = account("user", 0, 1); + let location: VersionedMultiLocation = VersionedMultiLocation::from(Parachain(1000).into()); + let metadata: AssetMetadata<<::Currency as Currency<::AccountId>>::Balance> = AssetMetadata{ + name: "name".into(), + symbol: "symbol".into(), + decimals: 18, + minimal_balance: 1u32.into() + }; + let mut balance: <::Currency as Currency<::AccountId>>::Balance = + 4_000_000_000u32.into(); + balance = balance * balance; + ::Currency::make_free_balance_be(&owner, + balance); + }: _(RawOrigin::Root, owner, Box::new(location), Box::new(metadata)) + + update_foreign_asset { + let owner: T::AccountId = account("user", 0, 1); + let location: VersionedMultiLocation = VersionedMultiLocation::from(Parachain(2000).into()); + let metadata: AssetMetadata<<::Currency as Currency<::AccountId>>::Balance> = AssetMetadata{ + name: "name".into(), + symbol: "symbol".into(), + decimals: 18, + minimal_balance: 1u32.into() + }; + let metadata2: AssetMetadata<<::Currency as Currency<::AccountId>>::Balance> = AssetMetadata{ + name: "name2".into(), + symbol: "symbol2".into(), + decimals: 18, + minimal_balance: 1u32.into() + }; + let mut balance: <::Currency as Currency<::AccountId>>::Balance = + 4_000_000_000u32.into(); + balance = balance * balance; + ::Currency::make_free_balance_be(&owner, balance); + Pallet::::register_foreign_asset(RawOrigin::Root.into(), owner, Box::new(location.clone()), Box::new(metadata))?; + }: _(RawOrigin::Root, 0, Box::new(location), Box::new(metadata2)) +} --- /dev/null +++ b/pallets/foreign-assets/src/impl_fungibles.rs @@ -0,0 +1,454 @@ +// 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 . + +//! Implementations for fungibles trait. + +use super::*; +use frame_system::Config as SystemConfig; + +use frame_support::traits::tokens::{DepositConsequence, WithdrawConsequence}; +use pallet_common::CollectionHandle; +use pallet_fungible::FungibleHandle; +use pallet_common::CommonCollectionOperations; +use up_data_structs::budget::Value; +use sp_runtime::traits::{CheckedAdd, CheckedSub}; + +impl fungibles::Inspect<::AccountId> for Pallet +where + T: orml_tokens::Config, + BalanceOf: From<::Balance>, + BalanceOf: From<::Balance>, + ::Balance: From>, + ::Balance: From>, +{ + type AssetId = AssetIds; + type Balance = BalanceOf; + + fn total_issuance(asset: Self::AssetId) -> Self::Balance { + log::trace!(target: "fassets::impl_foreign_assets", "impl_fungible total_issuance"); + + match asset { + AssetIds::NativeAssetId(NativeCurrency::Here) => { + as fungible::Inspect>::total_issuance() + .into() + } + AssetIds::NativeAssetId(NativeCurrency::Parent) => { + as fungibles::Inspect>::total_issuance( + AssetIds::NativeAssetId(NativeCurrency::Parent), + ) + .into() + } + AssetIds::ForeignAssetId(fid) => { + let target_collection_id = match >::get(fid) { + Some(v) => v, + None => return Zero::zero(), + }; + let collection_handle = match >::try_get(target_collection_id) { + Ok(v) => v, + Err(_) => return Zero::zero(), + }; + let collection = FungibleHandle::cast(collection_handle); + Self::Balance::try_from(collection.total_supply()).unwrap_or(Zero::zero()) + } + } + } + + fn minimum_balance(asset: Self::AssetId) -> Self::Balance { + log::trace!(target: "fassets::impl_foreign_assets", "impl_fungible minimum_balance"); + match asset { + AssetIds::NativeAssetId(NativeCurrency::Here) => { + as fungible::Inspect>::minimum_balance() + .into() + } + AssetIds::NativeAssetId(NativeCurrency::Parent) => { + as fungibles::Inspect>::minimum_balance( + AssetIds::NativeAssetId(NativeCurrency::Parent), + ) + .into() + } + AssetIds::ForeignAssetId(fid) => { + AssetMetadatas::::get(AssetIds::ForeignAssetId(fid)) + .map(|x| x.minimal_balance) + .unwrap_or_else(Zero::zero) + } + } + } + + fn balance(asset: Self::AssetId, who: &::AccountId) -> Self::Balance { + log::trace!(target: "fassets::impl_foreign_assets", "impl_fungible balance"); + match asset { + AssetIds::NativeAssetId(NativeCurrency::Here) => { + as fungible::Inspect>::balance(who).into() + } + AssetIds::NativeAssetId(NativeCurrency::Parent) => { + as fungibles::Inspect>::balance( + AssetIds::NativeAssetId(NativeCurrency::Parent), + who, + ) + .into() + } + AssetIds::ForeignAssetId(fid) => { + let target_collection_id = match >::get(fid) { + Some(v) => v, + None => return Zero::zero(), + }; + let collection_handle = match >::try_get(target_collection_id) { + Ok(v) => v, + Err(_) => return Zero::zero(), + }; + let collection = FungibleHandle::cast(collection_handle); + Self::Balance::try_from( + collection.balance(T::CrossAccountId::from_sub(who.clone()), TokenId(0)), + ) + .unwrap_or(Zero::zero()) + } + } + } + + fn reducible_balance( + asset: Self::AssetId, + who: &::AccountId, + keep_alive: bool, + ) -> Self::Balance { + log::trace!(target: "fassets::impl_foreign_assets", "impl_fungible reducible_balance"); + + match asset { + AssetIds::NativeAssetId(NativeCurrency::Here) => { + as fungible::Inspect>::reducible_balance( + who, keep_alive, + ) + .into() + } + AssetIds::NativeAssetId(NativeCurrency::Parent) => { + as fungibles::Inspect>::reducible_balance( + AssetIds::NativeAssetId(NativeCurrency::Parent), + who, + keep_alive, + ) + .into() + } + _ => Self::balance(asset, who), + } + } + + fn can_deposit( + asset: Self::AssetId, + who: &::AccountId, + amount: Self::Balance, + mint: bool, + ) -> DepositConsequence { + log::trace!(target: "fassets::impl_foreign_assets", "impl_fungible can_deposit"); + + match asset { + AssetIds::NativeAssetId(NativeCurrency::Here) => { + as fungible::Inspect>::can_deposit( + who, + amount.into(), + mint, + ) + } + AssetIds::NativeAssetId(NativeCurrency::Parent) => { + as fungibles::Inspect>::can_deposit( + AssetIds::NativeAssetId(NativeCurrency::Parent), + who, + amount.into(), + mint, + ) + } + _ => { + if amount.is_zero() { + return DepositConsequence::Success; + } + + let extential_deposit_value = T::ExistentialDeposit::get(); + let ed_value: u128 = match extential_deposit_value.try_into() { + Ok(val) => val, + Err(_) => return DepositConsequence::CannotCreate, + }; + let extential_deposit: Self::Balance = match ed_value.try_into() { + Ok(val) => val, + Err(_) => return DepositConsequence::CannotCreate, + }; + + let new_total_balance = match Self::balance(asset, who).checked_add(&amount) { + Some(x) => x, + None => return DepositConsequence::Overflow, + }; + + if new_total_balance < extential_deposit { + return DepositConsequence::BelowMinimum; + } + + DepositConsequence::Success + } + } + } + + fn can_withdraw( + asset: Self::AssetId, + who: &::AccountId, + amount: Self::Balance, + ) -> WithdrawConsequence { + log::trace!(target: "fassets::impl_foreign_assets", "impl_fungible can_withdraw"); + let value: u128 = match amount.try_into() { + Ok(val) => val, + Err(_) => return WithdrawConsequence::UnknownAsset, + }; + + match asset { + AssetIds::NativeAssetId(NativeCurrency::Here) => { + let this_amount: ::Balance = match value.try_into() { + Ok(val) => val, + Err(_) => { + return WithdrawConsequence::UnknownAsset; + } + }; + match as fungible::Inspect>::can_withdraw( + who, + this_amount, + ) { + WithdrawConsequence::NoFunds => WithdrawConsequence::NoFunds, + WithdrawConsequence::WouldDie => WithdrawConsequence::WouldDie, + WithdrawConsequence::UnknownAsset => WithdrawConsequence::UnknownAsset, + WithdrawConsequence::Underflow => WithdrawConsequence::Underflow, + WithdrawConsequence::Overflow => WithdrawConsequence::Overflow, + WithdrawConsequence::Frozen => WithdrawConsequence::Frozen, + WithdrawConsequence::Success => WithdrawConsequence::Success, + _ => WithdrawConsequence::NoFunds, + } + } + AssetIds::NativeAssetId(NativeCurrency::Parent) => { + let parent_amount: ::Balance = match value.try_into() { + Ok(val) => val, + Err(_) => { + return WithdrawConsequence::UnknownAsset; + } + }; + match as fungibles::Inspect>::can_withdraw( + AssetIds::NativeAssetId(NativeCurrency::Parent), + who, + parent_amount, + ) { + WithdrawConsequence::NoFunds => WithdrawConsequence::NoFunds, + WithdrawConsequence::WouldDie => WithdrawConsequence::WouldDie, + WithdrawConsequence::UnknownAsset => WithdrawConsequence::UnknownAsset, + WithdrawConsequence::Underflow => WithdrawConsequence::Underflow, + WithdrawConsequence::Overflow => WithdrawConsequence::Overflow, + WithdrawConsequence::Frozen => WithdrawConsequence::Frozen, + WithdrawConsequence::Success => WithdrawConsequence::Success, + _ => WithdrawConsequence::NoFunds, + } + } + _ => match Self::balance(asset, who).checked_sub(&amount) { + Some(_) => WithdrawConsequence::Success, + None => WithdrawConsequence::NoFunds, + }, + } + } +} + +impl fungibles::Mutate<::AccountId> for Pallet +where + T: orml_tokens::Config, + BalanceOf: From<::Balance>, + BalanceOf: From<::Balance>, + ::Balance: From>, + ::Balance: From>, + u128: From>, +{ + fn mint_into( + asset: Self::AssetId, + who: &::AccountId, + amount: Self::Balance, + ) -> DispatchResult { + //Self::do_mint(asset, who, amount, None) + log::trace!(target: "fassets::impl_foreign_assets", "impl_fungible mint_into {:?}", asset); + + match asset { + AssetIds::NativeAssetId(NativeCurrency::Here) => { + as fungible::Mutate>::mint_into( + who, + amount.into(), + ) + .into() + } + AssetIds::NativeAssetId(NativeCurrency::Parent) => { + as fungibles::Mutate>::mint_into( + AssetIds::NativeAssetId(NativeCurrency::Parent), + who, + amount.into(), + ) + .into() + } + AssetIds::ForeignAssetId(fid) => { + let target_collection_id = match >::get(fid) { + Some(v) => v, + None => { + return Err(DispatchError::Other( + "Associated collection not found for asset", + )) + } + }; + let collection = + FungibleHandle::cast(>::try_get(target_collection_id)?); + let account = T::CrossAccountId::from_sub(who.clone()); + + let amount_data: pallet_fungible::CreateItemData = + (account.clone(), amount.into()); + + pallet_fungible::Pallet::::create_item_foreign( + &collection, + &account, + amount_data, + &Value::new(0), + )?; + + Ok(()) + } + } + } + + fn burn_from( + asset: Self::AssetId, + who: &::AccountId, + amount: Self::Balance, + ) -> Result { + // let f = DebitFlags { keep_alive: false, best_effort: false }; + log::trace!(target: "fassets::impl_foreign_assets", "impl_fungible burn_from"); + + match asset { + AssetIds::NativeAssetId(NativeCurrency::Here) => { + match as fungible::Mutate>::burn_from( + who, + amount.into(), + ) { + Ok(v) => Ok(v.into()), + Err(e) => Err(e), + } + } + AssetIds::NativeAssetId(NativeCurrency::Parent) => { + match as fungibles::Mutate>::burn_from( + AssetIds::NativeAssetId(NativeCurrency::Parent), + who, + amount.into(), + ) { + Ok(v) => Ok(v.into()), + Err(e) => Err(e), + } + } + AssetIds::ForeignAssetId(fid) => { + let target_collection_id = match >::get(fid) { + Some(v) => v, + None => { + return Err(DispatchError::Other( + "Associated collection not found for asset", + )) + } + }; + let collection = + FungibleHandle::cast(>::try_get(target_collection_id)?); + pallet_fungible::Pallet::::burn_foreign( + &collection, + &T::CrossAccountId::from_sub(who.clone()), + amount.into(), + )?; + + Ok(amount) + } + } + } + + fn slash( + asset: Self::AssetId, + who: &::AccountId, + amount: Self::Balance, + ) -> Result { + // let f = DebitFlags { keep_alive: false, best_effort: true }; + log::trace!(target: "fassets::impl_foreign_assets", "impl_fungible slash"); + Ok(Self::burn_from(asset, who, amount)?) + } +} + +impl fungibles::Transfer for Pallet +where + T: orml_tokens::Config, + BalanceOf: From<::Balance>, + BalanceOf: From<::Balance>, + ::Balance: From>, + ::Balance: From>, + u128: From>, +{ + fn transfer( + asset: Self::AssetId, + source: &::AccountId, + dest: &::AccountId, + amount: Self::Balance, + keep_alive: bool, + ) -> Result { + // let f = TransferFlags { keep_alive, best_effort: false, burn_dust: false }; + log::trace!(target: "fassets::impl_foreign_assets", "impl_fungible transfer"); + + match asset { + AssetIds::NativeAssetId(NativeCurrency::Here) => { + match as fungible::Transfer>::transfer( + source, + dest, + amount.into(), + keep_alive, + ) { + Ok(_) => Ok(amount), + Err(_) => Err(DispatchError::Other( + "Bad amount to relay chain value conversion", + )), + } + } + AssetIds::NativeAssetId(NativeCurrency::Parent) => { + match as fungibles::Transfer>::transfer( + AssetIds::NativeAssetId(NativeCurrency::Parent), + source, + dest, + amount.into(), + keep_alive, + ) { + Ok(_) => Ok(amount), + Err(e) => Err(e), + } + } + AssetIds::ForeignAssetId(fid) => { + let target_collection_id = match >::get(fid) { + Some(v) => v, + None => { + return Err(DispatchError::Other( + "Associated collection not found for asset", + )) + } + }; + let collection = + FungibleHandle::cast(>::try_get(target_collection_id)?); + + pallet_fungible::Pallet::::transfer( + &collection, + &T::CrossAccountId::from_sub(source.clone()), + &T::CrossAccountId::from_sub(dest.clone()), + amount.into(), + &Value::new(0), + )?; + + Ok(amount) + } + } + } +} --- /dev/null +++ b/pallets/foreign-assets/src/lib.rs @@ -0,0 +1,498 @@ +// 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 . + +//! # Foreign assets +//! +//! - [`Config`] +//! - [`Call`] +//! - [`Pallet`] +//! +//! ## Overview +//! +//! The foreign assests pallet provides functions for: +//! +//! - Local and foreign assets management. The foreign assets can be updated without runtime upgrade. +//! - Bounds between asset and target collection for cross chain transfer and inner transfers. +//! +//! ## Overview +//! +//! Under construction + +#![cfg_attr(not(feature = "std"), no_std)] +#![allow(clippy::unused_unit)] + +use frame_support::{ + dispatch::DispatchResult, + ensure, + pallet_prelude::*, + traits::{fungible, fungibles, Currency, EnsureOrigin}, + RuntimeDebug, +}; +use frame_system::pallet_prelude::*; +use up_data_structs::{CollectionMode}; +use pallet_fungible::{Pallet as PalletFungible}; +use scale_info::{TypeInfo}; +use sp_runtime::{ + traits::{One, Zero}, + ArithmeticError, +}; +use sp_std::{boxed::Box, vec::Vec}; +use up_data_structs::{CollectionId, TokenId, CreateCollectionData}; + +// NOTE:v1::MultiLocation is used in storages, we would need to do migration if upgrade the +// MultiLocation in the future. +use xcm::opaque::latest::prelude::XcmError; +use xcm::{v1::MultiLocation, VersionedMultiLocation}; +use xcm_executor::{traits::WeightTrader, Assets}; + +use pallet_common::erc::CrossAccountId; + +#[cfg(feature = "std")] +use serde::{Deserialize, Serialize}; + +// TODO: Move to primitives +// Id of native currency. +// 0 - QTZ\UNQ +// 1 - KSM\DOT +#[derive( + Clone, + Copy, + Eq, + PartialEq, + PartialOrd, + Ord, + MaxEncodedLen, + RuntimeDebug, + Encode, + Decode, + TypeInfo, +)] +#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +pub enum NativeCurrency { + Here = 0, + Parent = 1, +} + +#[derive( + Clone, + Copy, + Eq, + PartialEq, + PartialOrd, + Ord, + MaxEncodedLen, + RuntimeDebug, + Encode, + Decode, + TypeInfo, +)] +#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +pub enum AssetIds { + ForeignAssetId(ForeignAssetId), + NativeAssetId(NativeCurrency), +} + +pub trait TryAsForeign { + fn try_as_foreign(asset: T) -> Option; +} + +impl TryAsForeign for AssetIds { + fn try_as_foreign(asset: AssetIds) -> Option { + match asset { + AssetIds::ForeignAssetId(id) => Some(id), + _ => None, + } + } +} + +pub type ForeignAssetId = u32; +pub type CurrencyId = AssetIds; + +mod impl_fungibles; +pub mod weights; + +#[cfg(feature = "runtime-benchmarks")] +mod benchmarking; + +pub use module::*; +pub use weights::WeightInfo; + +/// Type alias for currency balance. +pub type BalanceOf = + <::Currency as Currency<::AccountId>>::Balance; + +/// A mapping between ForeignAssetId and AssetMetadata. +pub trait AssetIdMapping { + /// Returns the AssetMetadata associated with a given ForeignAssetId. + fn get_asset_metadata(foreign_asset_id: ForeignAssetId) -> Option; + /// Returns the MultiLocation associated with a given ForeignAssetId. + fn get_multi_location(foreign_asset_id: ForeignAssetId) -> Option; + /// Returns the CurrencyId associated with a given MultiLocation. + fn get_currency_id(multi_location: MultiLocation) -> Option; +} + +pub struct XcmForeignAssetIdMapping(sp_std::marker::PhantomData); + +impl AssetIdMapping>> + for XcmForeignAssetIdMapping +{ + fn get_asset_metadata(foreign_asset_id: ForeignAssetId) -> Option>> { + log::trace!(target: "fassets::asset_metadatas", "call"); + Pallet::::asset_metadatas(AssetIds::ForeignAssetId(foreign_asset_id)) + } + + fn get_multi_location(foreign_asset_id: ForeignAssetId) -> Option { + log::trace!(target: "fassets::get_multi_location", "call"); + Pallet::::foreign_asset_locations(foreign_asset_id) + } + + fn get_currency_id(multi_location: MultiLocation) -> Option { + log::trace!(target: "fassets::get_currency_id", "call"); + Some(AssetIds::ForeignAssetId( + Pallet::::location_to_currency_ids(multi_location).unwrap_or(0), + )) + } +} + +#[frame_support::pallet] +pub mod module { + use super::*; + + #[pallet::config] + pub trait Config: + frame_system::Config + + pallet_common::Config + + pallet_fungible::Config + + orml_tokens::Config + + pallet_balances::Config + { + /// The overarching event type. + type Event: From> + IsType<::Event>; + + /// Currency type for withdraw and balance storage. + type Currency: Currency; + + /// Required origin for registering asset. + type RegisterOrigin: EnsureOrigin; + + /// Weight information for the extrinsics in this module. + type WeightInfo: WeightInfo; + } + + #[derive(Clone, Eq, PartialEq, RuntimeDebug, Encode, Decode, TypeInfo)] + pub struct AssetMetadata { + pub name: Vec, + pub symbol: Vec, + pub decimals: u8, + pub minimal_balance: Balance, + } + + #[pallet::error] + pub enum Error { + /// The given location could not be used (e.g. because it cannot be expressed in the + /// desired version of XCM). + BadLocation, + /// MultiLocation existed + MultiLocationExisted, + /// AssetId not exists + AssetIdNotExists, + /// AssetId exists + AssetIdExisted, + } + + #[pallet::event] + #[pallet::generate_deposit(fn deposit_event)] + pub enum Event { + /// The foreign asset registered. + ForeignAssetRegistered { + asset_id: ForeignAssetId, + asset_address: MultiLocation, + metadata: AssetMetadata>, + }, + /// The foreign asset updated. + ForeignAssetUpdated { + asset_id: ForeignAssetId, + asset_address: MultiLocation, + metadata: AssetMetadata>, + }, + /// The asset registered. + AssetRegistered { + asset_id: AssetIds, + metadata: AssetMetadata>, + }, + /// The asset updated. + AssetUpdated { + asset_id: AssetIds, + metadata: AssetMetadata>, + }, + } + + /// Next available Foreign AssetId ID. + /// + /// NextForeignAssetId: ForeignAssetId + #[pallet::storage] + #[pallet::getter(fn next_foreign_asset_id)] + pub type NextForeignAssetId = StorageValue<_, ForeignAssetId, ValueQuery>; + /// The storages for MultiLocations. + /// + /// ForeignAssetLocations: map ForeignAssetId => Option + #[pallet::storage] + #[pallet::getter(fn foreign_asset_locations)] + pub type ForeignAssetLocations = + StorageMap<_, Twox64Concat, ForeignAssetId, MultiLocation, OptionQuery>; + + /// The storages for CurrencyIds. + /// + /// LocationToCurrencyIds: map MultiLocation => Option + #[pallet::storage] + #[pallet::getter(fn location_to_currency_ids)] + pub type LocationToCurrencyIds = + StorageMap<_, Twox64Concat, MultiLocation, ForeignAssetId, OptionQuery>; + + /// The storages for AssetMetadatas. + /// + /// AssetMetadatas: map AssetIds => Option + #[pallet::storage] + #[pallet::getter(fn asset_metadatas)] + pub type AssetMetadatas = + StorageMap<_, Twox64Concat, AssetIds, AssetMetadata>, OptionQuery>; + + /// The storages for assets to fungible collection binding + /// + #[pallet::storage] + #[pallet::getter(fn asset_binding)] + pub type AssetBinding = + StorageMap<_, Twox64Concat, ForeignAssetId, CollectionId, OptionQuery>; + + #[pallet::pallet] + #[pallet::without_storage_info] + pub struct Pallet(_); + + #[pallet::call] + impl Pallet { + #[pallet::weight(::WeightInfo::register_foreign_asset())] + pub fn register_foreign_asset( + origin: OriginFor, + owner: T::AccountId, + location: Box, + metadata: Box>>, + ) -> DispatchResult { + T::RegisterOrigin::ensure_origin(origin.clone())?; + + let location: MultiLocation = (*location) + .try_into() + .map_err(|()| Error::::BadLocation)?; + + let md = metadata.clone(); + let name: Vec = md.name.into_iter().map(|x| x as u16).collect::>(); + let mut description: Vec = "Foreign assets collection for " + .encode_utf16() + .collect::>(); + description.append(&mut name.clone()); + + let data: CreateCollectionData = CreateCollectionData { + name: name.try_into().unwrap(), + description: description.try_into().unwrap(), + mode: CollectionMode::Fungible(md.decimals), + ..Default::default() + }; + + let bounded_collection_id = >::init_foreign_collection( + CrossAccountId::from_sub(owner), + data, + )?; + let foreign_asset_id = + Self::do_register_foreign_asset(&location, &metadata, bounded_collection_id)?; + + Self::deposit_event(Event::::ForeignAssetRegistered { + asset_id: foreign_asset_id, + asset_address: location, + metadata: *metadata, + }); + Ok(()) + } + + #[pallet::weight(::WeightInfo::update_foreign_asset())] + pub fn update_foreign_asset( + origin: OriginFor, + foreign_asset_id: ForeignAssetId, + location: Box, + metadata: Box>>, + ) -> DispatchResult { + T::RegisterOrigin::ensure_origin(origin)?; + + let location: MultiLocation = (*location) + .try_into() + .map_err(|()| Error::::BadLocation)?; + Self::do_update_foreign_asset(foreign_asset_id, &location, &metadata)?; + + Self::deposit_event(Event::::ForeignAssetUpdated { + asset_id: foreign_asset_id, + asset_address: location, + metadata: *metadata, + }); + Ok(()) + } + } +} + +impl Pallet { + fn get_next_foreign_asset_id() -> Result { + NextForeignAssetId::::try_mutate(|current| -> Result { + let id = *current; + *current = current + .checked_add(One::one()) + .ok_or(ArithmeticError::Overflow)?; + Ok(id) + }) + } + + fn do_register_foreign_asset( + location: &MultiLocation, + metadata: &AssetMetadata>, + bounded_collection_id: CollectionId, + ) -> Result { + let foreign_asset_id = Self::get_next_foreign_asset_id()?; + LocationToCurrencyIds::::try_mutate(location, |maybe_currency_ids| -> DispatchResult { + ensure!( + maybe_currency_ids.is_none(), + Error::::MultiLocationExisted + ); + *maybe_currency_ids = Some(foreign_asset_id); + // *maybe_currency_ids = Some(CurrencyId::ForeignAsset(foreign_asset_id)); + + ForeignAssetLocations::::try_mutate( + foreign_asset_id, + |maybe_location| -> DispatchResult { + ensure!(maybe_location.is_none(), Error::::MultiLocationExisted); + *maybe_location = Some(location.clone()); + + AssetMetadatas::::try_mutate( + AssetIds::ForeignAssetId(foreign_asset_id), + |maybe_asset_metadatas| -> DispatchResult { + ensure!(maybe_asset_metadatas.is_none(), Error::::AssetIdExisted); + *maybe_asset_metadatas = Some(metadata.clone()); + Ok(()) + }, + ) + }, + )?; + + AssetBinding::::try_mutate(foreign_asset_id, |collection_id| -> DispatchResult { + *collection_id = Some(bounded_collection_id); + Ok(()) + }) + })?; + + Ok(foreign_asset_id) + } + + fn do_update_foreign_asset( + foreign_asset_id: ForeignAssetId, + location: &MultiLocation, + metadata: &AssetMetadata>, + ) -> DispatchResult { + ForeignAssetLocations::::try_mutate( + foreign_asset_id, + |maybe_multi_locations| -> DispatchResult { + let old_multi_locations = maybe_multi_locations + .as_mut() + .ok_or(Error::::AssetIdNotExists)?; + + AssetMetadatas::::try_mutate( + AssetIds::ForeignAssetId(foreign_asset_id), + |maybe_asset_metadatas| -> DispatchResult { + ensure!( + maybe_asset_metadatas.is_some(), + Error::::AssetIdNotExists + ); + + // modify location + if location != old_multi_locations { + LocationToCurrencyIds::::remove(old_multi_locations.clone()); + LocationToCurrencyIds::::try_mutate( + location, + |maybe_currency_ids| -> DispatchResult { + ensure!( + maybe_currency_ids.is_none(), + Error::::MultiLocationExisted + ); + // *maybe_currency_ids = Some(CurrencyId::ForeignAsset(foreign_asset_id)); + *maybe_currency_ids = Some(foreign_asset_id); + Ok(()) + }, + )?; + } + *maybe_asset_metadatas = Some(metadata.clone()); + *old_multi_locations = location.clone(); + Ok(()) + }, + ) + }, + ) + } +} + +pub use frame_support::{ + traits::{ + fungibles::{Balanced, CreditOf}, + tokens::currency::Currency as CurrencyT, + OnUnbalanced as OnUnbalancedT, + }, + weights::{WeightToFeePolynomial, WeightToFee}, +}; + +pub struct FreeForAll< + WeightToFee: WeightToFeePolynomial, + AssetId: Get, + AccountId, + Currency: CurrencyT, + OnUnbalanced: OnUnbalancedT, +>( + Weight, + Currency::Balance, + PhantomData<(WeightToFee, AssetId, AccountId, Currency, OnUnbalanced)>, +); + +impl< + WeightToFee: WeightToFeePolynomial, + AssetId: Get, + AccountId, + Currency: CurrencyT, + OnUnbalanced: OnUnbalancedT, + > WeightTrader for FreeForAll +{ + fn new() -> Self { + Self(0, Zero::zero(), PhantomData) + } + + fn buy_weight(&mut self, weight: Weight, payment: Assets) -> Result { + log::trace!(target: "fassets::weight", "buy_weight weight: {:?}, payment: {:?}", weight, payment); + Ok(payment) + } +} +impl Drop + for FreeForAll +where + WeightToFee: WeightToFeePolynomial, + AssetId: Get, + Currency: CurrencyT, + OnUnbalanced: OnUnbalancedT, +{ + fn drop(&mut self) { + OnUnbalanced::on_unbalanced(Currency::issue(self.1)); + } +} --- /dev/null +++ b/pallets/foreign-assets/src/weights.rs @@ -0,0 +1,94 @@ +// Template adopted from https://github.com/paritytech/substrate/blob/master/.maintain/frame-weight-template.hbs + +//! Autogenerated weights for pallet_foreign_assets +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2022-09-16, STEPS: `50`, REPEAT: 80, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! EXECUTION: None, WASM-EXECUTION: Compiled, CHAIN: None, DB CACHE: 1024 + +// Executed Command: +// target/release/unique-collator +// benchmark +// pallet +// --pallet +// pallet-foreign-assets +// --wasm-execution +// compiled +// --extrinsic +// * +// --template +// .maintain/frame-weight-template.hbs +// --steps=50 +// --repeat=80 +// --heap-pages=4096 +// --output=./pallets/foreign-assets/src/weights.rs + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] +#![allow(missing_docs)] +#![allow(clippy::unnecessary_cast)] + +use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; +use sp_std::marker::PhantomData; + +/// Weight functions needed for pallet_foreign_assets. +pub trait WeightInfo { + fn register_foreign_asset() -> Weight; + fn update_foreign_asset() -> Weight; +} + +/// Weights for pallet_foreign_assets using the Substrate node and recommended hardware. +pub struct SubstrateWeight(PhantomData); +impl WeightInfo for SubstrateWeight { + // Storage: Common CreatedCollectionCount (r:1 w:1) + // Storage: Common DestroyedCollectionCount (r:1 w:0) + // Storage: System Account (r:2 w:2) + // Storage: ForeignAssets NextForeignAssetId (r:1 w:1) + // Storage: ForeignAssets LocationToCurrencyIds (r:1 w:1) + // Storage: ForeignAssets ForeignAssetLocations (r:1 w:1) + // Storage: ForeignAssets AssetMetadatas (r:1 w:1) + // Storage: ForeignAssets AssetBinding (r:1 w:1) + // Storage: Common CollectionPropertyPermissions (r:0 w:1) + // Storage: Common CollectionProperties (r:0 w:1) + // Storage: Common CollectionById (r:0 w:1) + fn register_foreign_asset() -> Weight { + (52_161_000 as Weight) + .saturating_add(T::DbWeight::get().reads(9 as Weight)) + .saturating_add(T::DbWeight::get().writes(11 as Weight)) + } + // Storage: ForeignAssets ForeignAssetLocations (r:1 w:1) + // Storage: ForeignAssets AssetMetadatas (r:1 w:1) + fn update_foreign_asset() -> Weight { + (19_111_000 as Weight) + .saturating_add(T::DbWeight::get().reads(2 as Weight)) + .saturating_add(T::DbWeight::get().writes(2 as Weight)) + } +} + +// For backwards compatibility and tests +impl WeightInfo for () { + // Storage: Common CreatedCollectionCount (r:1 w:1) + // Storage: Common DestroyedCollectionCount (r:1 w:0) + // Storage: System Account (r:2 w:2) + // Storage: ForeignAssets NextForeignAssetId (r:1 w:1) + // Storage: ForeignAssets LocationToCurrencyIds (r:1 w:1) + // Storage: ForeignAssets ForeignAssetLocations (r:1 w:1) + // Storage: ForeignAssets AssetMetadatas (r:1 w:1) + // Storage: ForeignAssets AssetBinding (r:1 w:1) + // Storage: Common CollectionPropertyPermissions (r:0 w:1) + // Storage: Common CollectionProperties (r:0 w:1) + // Storage: Common CollectionById (r:0 w:1) + fn register_foreign_asset() -> Weight { + (52_161_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(9 as Weight)) + .saturating_add(RocksDbWeight::get().writes(11 as Weight)) + } + // Storage: ForeignAssets ForeignAssetLocations (r:1 w:1) + // Storage: ForeignAssets AssetMetadatas (r:1 w:1) + fn update_foreign_asset() -> Weight { + (19_111_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(2 as Weight)) + .saturating_add(RocksDbWeight::get().writes(2 as Weight)) + } +} --- a/pallets/fungible/src/lib.rs +++ b/pallets/fungible/src/lib.rs @@ -83,8 +83,8 @@ use frame_support::{ensure}; use pallet_evm::account::CrossAccountId; use up_data_structs::{ - AccessMode, CollectionId, TokenId, CreateCollectionData, mapping::TokenAddressMapping, - budget::Budget, + AccessMode, CollectionId, CollectionFlags, TokenId, CreateCollectionData, + mapping::TokenAddressMapping, budget::Budget, }; use pallet_common::{ Error as CommonError, Event as CommonEvent, Pallet as PalletCommon, @@ -212,9 +212,25 @@ owner: T::CrossAccountId, data: CreateCollectionData, ) -> Result { - >::init_collection(owner, data, false) + >::init_collection(owner, data, CollectionFlags::default()) } + /// Initializes the collection with ForeignCollection flag. Returns [CollectionId] on success, [DispatchError] otherwise. + pub fn init_foreign_collection( + owner: T::CrossAccountId, + data: CreateCollectionData, + ) -> Result { + let id = >::init_collection( + owner, + data, + CollectionFlags { + foreign: true, + ..Default::default() + }, + )?; + Ok(id) + } + /// Destroys a collection. pub fn destroy_collection( collection: FungibleHandle, @@ -257,6 +273,9 @@ .checked_sub(amount) .ok_or(>::TokenValueTooLow)?; + // Foreign collection check + ensure!(!collection.flags.foreign, >::NoPermission); + if collection.permissions.access() == AccessMode::AllowList { collection.check_allowlist(owner)?; } @@ -288,6 +307,46 @@ Ok(()) } + /// Burns the specified amount of the token. + pub fn burn_foreign( + collection: &FungibleHandle, + owner: &T::CrossAccountId, + amount: u128, + ) -> DispatchResult { + let total_supply = >::get(collection.id) + .checked_sub(amount) + .ok_or(>::TokenValueTooLow)?; + + let balance = >::get((collection.id, owner)) + .checked_sub(amount) + .ok_or(>::TokenValueTooLow)?; + // ========= + + if balance == 0 { + >::remove((collection.id, owner)); + >::unnest_if_nested(owner, collection.id, TokenId::default()); + } else { + >::insert((collection.id, owner), balance); + } + >::insert(collection.id, total_supply); + + >::deposit_log( + ERC20Events::Transfer { + from: *owner.as_eth(), + to: H160::default(), + value: amount.into(), + } + .to_log(collection_id_to_address(collection.id)), + ); + >::deposit_event(CommonEvent::ItemDestroyed( + collection.id, + TokenId::default(), + owner.clone(), + amount, + )); + Ok(()) + } + /// Transfers the specified amount of tokens. Will check that /// the transfer is allowed for the token. /// @@ -366,25 +425,14 @@ } /// Minting tokens for multiple IDs. - /// See [`create_item`][`Pallet::create_item`] for more details. - pub fn create_multiple_items( + /// It is a utility function used in [`create_multiple_items`][`Pallet::create_multiple_items`] + /// and [`create_multiple_items_foreign`][`Pallet::create_multiple_items_foreign`] + pub fn create_multiple_items_common( collection: &FungibleHandle, sender: &T::CrossAccountId, data: BTreeMap, nesting_budget: &dyn Budget, ) -> DispatchResult { - if !collection.is_owner_or_admin(sender) { - ensure!( - collection.permissions.mint_mode(), - >::PublicMintingNotAllowed - ); - collection.check_allowlist(sender)?; - - for (owner, _) in data.iter() { - collection.check_allowlist(owner)?; - } - } - let total_supply = data .iter() .map(|(_, v)| *v) @@ -442,6 +490,43 @@ Ok(()) } + /// Minting tokens for multiple IDs. + /// See [`create_item`][`Pallet::create_item`] for more details. + pub fn create_multiple_items( + collection: &FungibleHandle, + sender: &T::CrossAccountId, + data: BTreeMap, + nesting_budget: &dyn Budget, + ) -> DispatchResult { + // Foreign collection check + ensure!(!collection.flags.foreign, >::NoPermission); + + if !collection.is_owner_or_admin(sender) { + ensure!( + collection.permissions.mint_mode(), + >::PublicMintingNotAllowed + ); + collection.check_allowlist(sender)?; + + for (owner, _) in data.iter() { + collection.check_allowlist(owner)?; + } + } + + Self::create_multiple_items_common(collection, sender, data, nesting_budget) + } + + /// Minting tokens for multiple IDs. + /// See [`create_item_foreign`][`Pallet::create_item_foreign`] for more details. + pub fn create_multiple_items_foreign( + collection: &FungibleHandle, + sender: &T::CrossAccountId, + data: BTreeMap, + nesting_budget: &dyn Budget, + ) -> DispatchResult { + Self::create_multiple_items_common(collection, sender, data, nesting_budget) + } + fn set_allowance_unchecked( collection: &FungibleHandle, owner: &T::CrossAccountId, @@ -615,6 +700,24 @@ ) } + /// Creates fungible token. + /// + /// - `data`: Contains user who will become the owners of the tokens and amount + /// of tokens he will receive. + pub fn create_item_foreign( + collection: &FungibleHandle, + sender: &T::CrossAccountId, + data: CreateItemData, + nesting_budget: &dyn Budget, + ) -> DispatchResult { + Self::create_multiple_items_foreign( + collection, + sender, + [(data.0, data.1)].into_iter().collect(), + nesting_budget, + ) + } + /// Returns 10 tokens owners in no particular order /// /// There is no direct way to get token holders in ascending order, --- a/pallets/nonfungible/src/lib.rs +++ b/pallets/nonfungible/src/lib.rs @@ -100,10 +100,10 @@ weights::{PostDispatchInfo, Pays}, }; use up_data_structs::{ - AccessMode, CollectionId, CustomDataLimit, TokenId, CreateCollectionData, CreateNftExData, - mapping::TokenAddressMapping, budget::Budget, Property, PropertyPermission, PropertyKey, - PropertyValue, PropertyKeyPermission, Properties, PropertyScope, TrySetProperty, TokenChild, - AuxPropertyValue, + AccessMode, CollectionId, CollectionFlags, CustomDataLimit, TokenId, CreateCollectionData, + CreateNftExData, mapping::TokenAddressMapping, budget::Budget, Property, PropertyPermission, + PropertyKey, PropertyValue, PropertyKeyPermission, Properties, PropertyScope, TrySetProperty, + TokenChild, AuxPropertyValue, }; use pallet_evm::{account::CrossAccountId, Pallet as PalletEvm}; use pallet_common::{ @@ -408,7 +408,14 @@ data: CreateCollectionData, is_external: bool, ) -> Result { - >::init_collection(owner, data, is_external) + >::init_collection( + owner, + data, + CollectionFlags { + external: is_external, + ..Default::default() + }, + ) } /// Destroy NFT collection --- a/pallets/refungible/src/lib.rs +++ b/pallets/refungible/src/lib.rs @@ -112,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, CollectionMode, CollectionPropertiesVec, - CreateCollectionData, CustomDataLimit, mapping::TokenAddressMapping, MAX_ITEMS_PER_BATCH, - MAX_REFUNGIBLE_PIECES, Property, PropertyKey, PropertyKeyPermission, PropertyPermission, - PropertyScope, PropertyValue, TokenId, TrySetProperty, + AccessMode, budget::Budget, CollectionId, CollectionMode, CollectionFlags, + 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; @@ -375,7 +375,7 @@ owner: T::CrossAccountId, data: CreateCollectionData, ) -> Result { - >::init_collection(owner, data, false) + >::init_collection(owner, data, CollectionFlags::default()) } /// Destroy RFT collection --- a/pallets/scheduler/Cargo.toml +++ b/pallets/scheduler/Cargo.toml @@ -25,7 +25,7 @@ frame-benchmarking = { default-features = false, optional = true, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" } up-sponsorship = { version = "0.1.0", default-features = false, git = "https://github.com/uniquenetwork/pallet-sponsoring", branch = "polkadot-v0.9.27" } -log = { version = "0.4.14", default-features = false } +log = { version = "0.4.16", default-features = false } [dev-dependencies] sp-core = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" } --- a/primitives/data-structs/Cargo.toml +++ b/primitives/data-structs/Cargo.toml @@ -27,6 +27,7 @@ struct-versioning = { path = "../../crates/struct-versioning" } pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27-fee-limit" } rmrk-traits = { default-features = false, path = "../rmrk-traits" } +bondrewd = { version = "0.1.14", features = ["derive"], default-features = false } [features] default = ["std"] --- /dev/null +++ b/primitives/data-structs/src/bondrewd_codec.rs @@ -0,0 +1,31 @@ +//! Integration between bondrewd and parity scale codec +//! Maybe we can move it to scale-codec itself in future? + +#[macro_export] +macro_rules! bondrewd_codec { + ($T:ty) => { + impl Encode for $T { + fn encode_to(&self, dest: &mut O) { + dest.write(&self.into_bytes()) + } + } + impl codec::Decode for $T { + fn decode(from: &mut I) -> Result { + let mut bytes = [0; Self::BYTE_SIZE]; + from.read(&mut bytes)?; + Ok(Self::from_bytes(bytes)) + } + } + impl MaxEncodedLen for $T { + fn max_encoded_len() -> usize { + Self::BYTE_SIZE + } + } + impl TypeInfo for $T { + type Identity = [u8; Self::BYTE_SIZE]; + fn type_info() -> scale_info::Type { + <[u8; Self::BYTE_SIZE] as TypeInfo>::type_info() + } + } + }; +} --- a/primitives/data-structs/src/lib.rs +++ b/primitives/data-structs/src/lib.rs @@ -36,6 +36,7 @@ use sp_core::U256; use sp_runtime::{ArithmeticError, sp_std::prelude::Vec, Permill}; use codec::{Decode, Encode, EncodeLike, MaxEncodedLen}; +use bondrewd::Bitfields; use frame_support::{BoundedVec, traits::ConstU32}; use derivative::Derivative; use scale_info::TypeInfo; @@ -54,6 +55,7 @@ FixedPart as RmrkFixedPart, SlotPart as RmrkSlotPart, }; +mod bondrewd_codec; mod bounded; pub mod budget; pub mod mapping; @@ -357,6 +359,21 @@ pub type CollectionDescription = BoundedVec>; pub type CollectionTokenPrefix = BoundedVec>; +#[derive(Bitfields, Clone, Copy, PartialEq, Eq, Debug, Default)] +#[bondrewd(enforce_bytes = 1)] +pub struct CollectionFlags { + /// Tokens in foreign collections can be transferred, but not burnt + #[bondrewd(bits = "0..1")] + pub foreign: bool, + /// External collections can't be managed using `unique` api + #[bondrewd(bits = "7..8")] + pub external: bool, + + #[bondrewd(reserve, bits = "1..7")] + pub reserved: u8, +} +bondrewd_codec!(CollectionFlags); + /// Base structure for represent collection. /// /// Used to provide basic functionality for all types of collections. @@ -404,9 +421,8 @@ #[version(2.., upper(Default::default()))] pub permissions: CollectionPermissions, - /// Marks that this collection is not "unique", and managed from external. - #[version(2.., upper(false))] - pub external_collection: bool, + #[version(2.., upper(Default::default()))] + pub flags: CollectionFlags, #[version(..2)] pub variable_on_chain_schema: BoundedVec>, @@ -454,6 +470,9 @@ /// Is collection read only. pub read_only: bool, + + /// Is collection is foreign. + pub foreign: bool, } /// Data used for create collection. --- a/primitives/data-structs/src/migration.rs +++ b/primitives/data-structs/src/migration.rs @@ -38,3 +38,26 @@ test_to_option(SponsoringRateLimit::SponsoringDisabled); test_to_option(SponsoringRateLimit::Blocks(10)); } + +#[test] +fn collection_flags_have_same_encoding_as_bool() { + use crate::CollectionFlags; + use codec::Encode; + + assert_eq!( + true.encode(), + CollectionFlags { + external: true, + ..Default::default() + } + .encode() + ); + assert_eq!( + false.encode(), + CollectionFlags { + external: false, + ..Default::default() + } + .encode() + ); +} --- a/runtime/common/config/orml.rs +++ b/runtime/common/config/orml.rs @@ -14,19 +14,87 @@ // You should have received a copy of the GNU General Public License // along with Unique Network. If not, see . -use frame_support::parameter_types; +use frame_support::{ + parameter_types, + traits::{Contains, Everything}, + weights::Weight, +}; use frame_system::EnsureSigned; -use crate::{Runtime, Event, RelayChainBlockNumberProvider}; +use orml_traits::{location::AbsoluteReserveProvider, parameter_type_with_key}; +use sp_runtime::traits::Convert; +use xcm::v1::{Junction::*, Junctions::*, MultiLocation, NetworkId}; +use xcm_builder::LocationInverter; +use xcm_executor::XcmExecutor; +use sp_std::{vec, vec::Vec}; +use pallet_foreign_assets::{CurrencyId, NativeCurrency}; +use crate::{ + Runtime, Event, RelayChainBlockNumberProvider, + runtime_common::config::{ + xcm::{ + SelfLocation, Weigher, XcmConfig, Ancestry, + xcm_assets::{CurrencyIdConvert}, + }, + pallets::TreasuryAccountId, + substrate::{MaxLocks, MaxReserves}, + }, +}; + use up_common::{ types::{AccountId, Balance}, constants::*, }; +// Signed version of balance +pub type Amount = i128; + parameter_types! { pub const MinVestedTransfer: Balance = 10 * UNIQUE; pub const MaxVestingSchedules: u32 = 28; + + pub const BaseXcmWeight: Weight = 100_000_000; // TODO: recheck this + pub const MaxAssetsForTransfer: usize = 2; +} + +parameter_type_with_key! { + pub ParachainMinFee: |_location: MultiLocation| -> Option { + Some(100_000_000_000) + }; +} + +parameter_type_with_key! { + pub ExistentialDeposits: |currency_id: CurrencyId| -> Balance { + match currency_id { + CurrencyId::NativeAssetId(symbol) => match symbol { + NativeCurrency::Here => 0, + NativeCurrency::Parent=> 0, + }, + _ => 100_000 + } + }; +} + +pub fn get_all_module_accounts() -> Vec { + vec![TreasuryAccountId::get()] } +pub struct DustRemovalWhitelist; +impl Contains for DustRemovalWhitelist { + fn contains(a: &AccountId) -> bool { + get_all_module_accounts().contains(a) + } +} + +pub struct AccountIdToMultiLocation; +impl Convert for AccountIdToMultiLocation { + fn convert(account: AccountId) -> MultiLocation { + X1(AccountId32 { + network: NetworkId::Any, + id: account.into(), + }) + .into() + } +} + impl orml_vesting::Config for Runtime { type Event = Event; type Currency = pallet_balances::Pallet; @@ -36,3 +104,38 @@ type MaxVestingSchedules = MaxVestingSchedules; type BlockNumberProvider = RelayChainBlockNumberProvider; } + +impl orml_tokens::Config for Runtime { + type Event = Event; + type Balance = Balance; + type Amount = Amount; + type CurrencyId = CurrencyId; + type WeightInfo = (); + type ExistentialDeposits = ExistentialDeposits; + type OnDust = orml_tokens::TransferDust; + type MaxLocks = MaxLocks; + type MaxReserves = MaxReserves; + // TODO: Add all module accounts + type DustRemovalWhitelist = DustRemovalWhitelist; + /// The id type for named reserves. + type ReserveIdentifier = (); + type OnNewTokenAccount = (); + type OnKilledTokenAccount = (); +} + +impl orml_xtokens::Config for Runtime { + type Event = Event; + type Balance = Balance; + type CurrencyId = CurrencyId; + type CurrencyIdConvert = CurrencyIdConvert; + type AccountIdToMultiLocation = AccountIdToMultiLocation; + type SelfLocation = SelfLocation; + type XcmExecutor = XcmExecutor>; + type Weigher = Weigher; + type BaseXcmWeight = BaseXcmWeight; + type LocationInverter = LocationInverter; + type MaxAssetsForTransfer = MaxAssetsForTransfer; + type MinXcmFee = ParachainMinFee; + type MultiLocationsFilter = Everything; + type ReserveProvider = AbsoluteReserveProvider; +} --- /dev/null +++ b/runtime/common/config/pallets/foreign_asset.rs @@ -0,0 +1,9 @@ +use crate::{Runtime, Event, Balances}; +use up_common::types::AccountId; + +impl pallet_foreign_assets::Config for Runtime { + type Event = Event; + type Currency = Balances; + type RegisterOrigin = frame_system::EnsureRoot; + type WeightInfo = pallet_foreign_assets::weights::SubstrateWeight; +} --- a/runtime/common/config/pallets/mod.rs +++ b/runtime/common/config/pallets/mod.rs @@ -40,6 +40,9 @@ #[cfg(feature = "scheduler")] pub mod scheduler; +#[cfg(feature = "foreign-assets")] +pub mod foreign_asset; + #[cfg(feature = "app-promotion")] pub mod app_promotion; --- a/runtime/common/config/xcm.rs +++ /dev/null @@ -1,302 +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 . - -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, - // Sibling parachain origins convert to AccountId via the `ParaId::into`. - SiblingParachainConvertsVia, - // Straight up local `AccountId32` origins just alias directly to `AccountId`. - AccountId32Aliases, -); - -pub struct OnlySelfCurrency; -impl> MatchesFungible for OnlySelfCurrency { - fn matches_fungible(a: &MultiAsset) -> Option { - 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,); - -/// 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, - // ..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, - // Native converter for Relay-chain (Parent) location; will converts to a `Relay` origin when - // recognised. - RelayChainAsNative, - // Native converter for sibling Parachains; will convert to a `SiblingPara` origin when - // recognised. - SiblingParachainAsNative, - // Superuser converter for the Relay-chain (Parent) location. This will allow it to issue a - // transaction from the Root origin. - ParentAsSuperuser, - // Native signed account converter; this just converts an `AccountId32` origin into a normal - // `Origin::Signed` origin of the same 32-byte value. - SignedAccountId32AsNative, - // Xcm origins can be represented natively under the Xcm pallet's Xcm origin. - XcmPassthrough, -); - -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 { parents: 1, interior: Here } | - MultiLocation { parents: 1, interior: X1(Plurality { id: BodyId::Unit, .. }) } - }; -} - -pub type Barrier = ( - TakeWeightCredit, - AllowTopLevelPaidExecutionFrom, - // ^^^ Parent & its unit plurality gets free execution -); - -pub struct UsingOnlySelfCurrencyComponents< - WeightToFee: WeightToFeePolynomial, - AssetId: Get, - AccountId, - Currency: CurrencyT, - OnUnbalanced: OnUnbalancedT, ->( - Weight, - Currency::Balance, - PhantomData<(WeightToFee, AssetId, AccountId, Currency, OnUnbalanced)>, -); -impl< - WeightToFee: WeightToFeePolynomial, - AssetId: Get, - AccountId, - Currency: CurrencyT, - OnUnbalanced: OnUnbalancedT, - > WeightTrader - for UsingOnlySelfCurrencyComponents -{ - fn new() -> Self { - Self(0, Zero::zero(), PhantomData) - } - - fn buy_weight(&mut self, weight: Weight, payment: Assets) -> Result { - 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 { - 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, - AssetId: Get, - AccountId, - Currency: CurrencyT, - OnUnbalanced: OnUnbalancedT, - > Drop - for UsingOnlySelfCurrencyComponents -{ - fn drop(&mut self) { - OnUnbalanced::on_unbalanced(Currency::issue(self.1)); - } -} - -pub struct XcmConfig(PhantomData); -impl Config for XcmConfig -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; - type Barrier = Barrier; - type Weigher = FixedWeightBounds; - type Trader = UsingOnlySelfCurrencyComponents< - pallet_configuration::WeightToFee, - 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; - type XcmRouter = XcmRouter; - type ExecuteXcmOrigin = EnsureXcmOrigin; - type XcmExecuteFilter = Everything; - type XcmExecutor = XcmExecutor>; - type XcmTeleportFilter = Everything; - type XcmReserveTransferFilter = Everything; - type Weigher = FixedWeightBounds; - type LocationInverter = LocationInverter; - 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>; -} - -impl cumulus_pallet_xcmp_queue::Config for Runtime { - type WeightInfo = (); - type Event = Event; - type XcmExecutor = XcmExecutor>; - type ChannelInfo = ParachainSystem; - type VersionWrapper = (); - type ExecuteOverweightOrigin = frame_system::EnsureRoot; - type ControllerOrigin = EnsureRoot; - type ControllerOriginConverter = XcmOriginToTransactDispatchOrigin; -} - -impl cumulus_pallet_dmp_queue::Config for Runtime { - type Event = Event; - type XcmExecutor = XcmExecutor>; - type ExecuteOverweightOrigin = frame_system::EnsureRoot; -} --- /dev/null +++ b/runtime/common/config/xcm/foreignassets.rs @@ -0,0 +1,198 @@ +// 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 . + +use frame_support::{ + traits::{Contains, Get, fungibles}, + parameter_types, +}; +use sp_runtime::traits::{Zero, Convert}; +use xcm::v1::{Junction::*, MultiLocation, Junctions::*}; +use xcm::latest::MultiAsset; +use xcm_builder::{FungiblesAdapter, ConvertedConcreteAssetId}; +use xcm_executor::traits::{Convert as ConvertXcm, JustTry, FilterAssetLocation}; +use pallet_foreign_assets::{ + AssetIds, AssetIdMapping, XcmForeignAssetIdMapping, NativeCurrency, FreeForAll, TryAsForeign, + ForeignAssetId, CurrencyId, +}; +use sp_std::{borrow::Borrow, marker::PhantomData}; +use crate::{Runtime, Balances, ParachainInfo, PolkadotXcm, ForeignAssets}; + +use super::{LocationToAccountId, RelayLocation}; + +use up_common::types::{AccountId, Balance}; + +parameter_types! { + pub CheckingAccount: AccountId = PolkadotXcm::check_account(); +} + +/// Allow checking in assets that have issuance > 0. +pub struct NonZeroIssuance(PhantomData<(AccountId, ForeignAssets)>); + +impl Contains<>::AssetId> + for NonZeroIssuance +where + ForeignAssets: fungibles::Inspect, +{ + fn contains(id: &>::AssetId) -> bool { + !ForeignAssets::total_issuance(*id).is_zero() + } +} + +pub struct AsInnerId(PhantomData<(AssetId, ConvertAssetId)>); +impl> + ConvertXcm for AsInnerId +where + AssetId: Borrow, + AssetId: TryAsForeign, + AssetIds: Borrow, +{ + fn convert_ref(id: impl Borrow) -> Result { + let id = id.borrow(); + + log::trace!( + target: "xcm::AsInnerId::Convert", + "AsInnerId {:?}", + id + ); + + let parent = MultiLocation::parent(); + let here = MultiLocation::here(); + let self_location = MultiLocation::new(1, X1(Parachain(ParachainInfo::get().into()))); + + if *id == parent { + return ConvertAssetId::convert_ref(AssetIds::NativeAssetId(NativeCurrency::Parent)); + } + + if *id == here || *id == self_location { + return ConvertAssetId::convert_ref(AssetIds::NativeAssetId(NativeCurrency::Here)); + } + + match XcmForeignAssetIdMapping::::get_currency_id(id.clone()) { + Some(AssetIds::ForeignAssetId(foreign_asset_id)) => { + ConvertAssetId::convert_ref(AssetIds::ForeignAssetId(foreign_asset_id)) + } + _ => ConvertAssetId::convert_ref(AssetIds::ForeignAssetId(0)), + } + } + + fn reverse_ref(what: impl Borrow) -> Result { + log::trace!( + target: "xcm::AsInnerId::Reverse", + "AsInnerId", + ); + + let asset_id = what.borrow(); + + let parent_id = + ConvertAssetId::convert_ref(AssetIds::NativeAssetId(NativeCurrency::Parent)).unwrap(); + let here_id = + ConvertAssetId::convert_ref(AssetIds::NativeAssetId(NativeCurrency::Here)).unwrap(); + + if asset_id.clone() == parent_id { + return Ok(MultiLocation::parent()); + } + + if asset_id.clone() == here_id { + return Ok(MultiLocation::new( + 1, + X1(Parachain(ParachainInfo::get().into())), + )); + } + + match >::try_as_foreign(asset_id.clone()) { + Some(fid) => match XcmForeignAssetIdMapping::::get_multi_location(fid) { + Some(location) => Ok(location), + None => Err(()), + }, + None => Err(()), + } + } +} + +/// Means for transacting assets besides the native currency on this chain. +pub type FungiblesTransactor = FungiblesAdapter< + // Use this fungibles implementation: + ForeignAssets, + // Use this currency when it is a fungible asset matching the given location or name: + ConvertedConcreteAssetId, JustTry>, + // Convert an XCM MultiLocation into a local account id: + LocationToAccountId, + // Our chain's account ID type (we can't get away without mentioning it explicitly): + AccountId, + // We only want to allow teleports of known assets. We use non-zero issuance as an indication + // that this asset is known. + NonZeroIssuance, + // The account to use for tracking teleports. + CheckingAccount, +>; + +/// Means for transacting assets on this chain. +pub type AssetTransactors = FungiblesTransactor; + +pub struct AllAsset; +impl FilterAssetLocation for AllAsset { + fn filter_asset_location(_asset: &MultiAsset, _origin: &MultiLocation) -> bool { + true + } +} + +pub type IsReserve = AllAsset; + +pub type Trader = FreeForAll< + pallet_configuration::WeightToFee, + RelayLocation, + AccountId, + Balances, + (), +>; + +pub struct CurrencyIdConvert; +impl Convert> for CurrencyIdConvert { + fn convert(id: AssetIds) -> Option { + match id { + AssetIds::NativeAssetId(NativeCurrency::Here) => Some(MultiLocation::new( + 1, + X1(Parachain(ParachainInfo::get().into())), + )), + AssetIds::NativeAssetId(NativeCurrency::Parent) => Some(MultiLocation::parent()), + AssetIds::ForeignAssetId(foreign_asset_id) => { + XcmForeignAssetIdMapping::::get_multi_location(foreign_asset_id) + } + } + } +} + +impl Convert> for CurrencyIdConvert { + fn convert(location: MultiLocation) -> Option { + if location == MultiLocation::here() + || location == MultiLocation::new(1, X1(Parachain(ParachainInfo::get().into()))) + { + return Some(AssetIds::NativeAssetId(NativeCurrency::Here)); + } + + if location == MultiLocation::parent() { + return Some(AssetIds::NativeAssetId(NativeCurrency::Parent)); + } + + if let Some(currency_id) = + XcmForeignAssetIdMapping::::get_currency_id(location.clone()) + { + return Some(currency_id); + } + + None + } +} --- /dev/null +++ b/runtime/common/config/xcm/mod.rs @@ -0,0 +1,268 @@ +// 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 . + +use frame_support::{ + traits::{Everything, Get}, + weights::Weight, + parameter_types, +}; +use frame_system::EnsureRoot; +use pallet_xcm::XcmPassthrough; +use polkadot_parachain::primitives::Sibling; +use xcm::v1::{Junction::*, MultiLocation, NetworkId}; +use xcm::latest::prelude::*; +use xcm_builder::{ + AccountId32Aliases, EnsureXcmOrigin, FixedWeightBounds, LocationInverter, ParentAsSuperuser, + RelayChainAsNative, SiblingParachainAsNative, SiblingParachainConvertsVia, + SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, ParentIsPreset, +}; +use xcm_executor::{Config, XcmExecutor, traits::ShouldExecute}; +use sp_std::{marker::PhantomData, vec::Vec}; +use crate::{ + Runtime, Call, Event, Origin, ParachainInfo, ParachainSystem, PolkadotXcm, XcmpQueue, + xcm_barrier::Barrier, +}; + +use up_common::types::AccountId; + +#[cfg(feature = "foreign-assets")] +pub mod foreignassets; + +#[cfg(not(feature = "foreign-assets"))] +pub mod nativeassets; + +#[cfg(feature = "foreign-assets")] +pub use foreignassets as xcm_assets; + +#[cfg(not(feature = "foreign-assets"))] +pub use nativeassets as xcm_assets; + +use xcm_assets::{AssetTransactors, IsReserve, Trader}; + +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(); + pub SelfLocation: MultiLocation = MultiLocation::new(1, X1(Parachain(ParachainInfo::get().into()))); + + // One XCM operation is 1_000_000 weight - almost certainly a conservative estimate. + pub UnitWeightCost: Weight = 1_000_000; + pub const MaxInstructions: u32 = 100; +} + +/// 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, + // Sibling parachain origins convert to AccountId via the `ParaId::into`. + SiblingParachainConvertsVia, + // Straight up local `AccountId32` origins just alias directly to `AccountId`. + AccountId32Aliases, +); + +/// No local origins on this chain are allowed to dispatch XCM sends/executions. +pub type LocalOriginToLocation = (SignedToAccountId32,); + +/// 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, + // ..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, + // Native converter for Relay-chain (Parent) location; will converts to a `Relay` origin when + // recognised. + RelayChainAsNative, + // Native converter for sibling Parachains; will convert to a `SiblingPara` origin when + // recognised. + SiblingParachainAsNative, + // Superuser converter for the Relay-chain (Parent) location. This will allow it to issue a + // transaction from the Root origin. + ParentAsSuperuser, + // Native signed account converter; this just converts an `AccountId32` origin into a normal + // `Origin::Signed` origin of the same 32-byte value. + SignedAccountId32AsNative, + // Xcm origins can be represented natively under the Xcm pallet's Xcm origin. + XcmPassthrough, +); + +pub trait TryPass { + fn try_pass(origin: &MultiLocation, message: &mut Xcm) -> Result<(), ()>; +} + +#[impl_trait_for_tuples::impl_for_tuples(30)] +impl TryPass for Tuple { + fn try_pass(origin: &MultiLocation, message: &mut Xcm) -> Result<(), ()> { + for_tuples!( #( + Tuple::try_pass(origin, message)?; + )* ); + + Ok(()) + } +} + +pub struct DenyTransact; +impl TryPass for DenyTransact { + fn try_pass(_origin: &MultiLocation, message: &mut Xcm) -> Result<(), ()> { + let transact_inst = message + .0 + .iter() + .find(|inst| matches![inst, Instruction::Transact { .. }]); + + if transact_inst.is_some() { + log::warn!( + target: "xcm::barrier", + "transact XCM rejected" + ); + + Err(()) + } else { + Ok(()) + } + } +} + +/// Deny executing the XCM if it matches any of the Deny filter regardless of anything else. +/// If it passes the Deny, and matches one of the Allow cases then it is let through. +pub struct DenyThenTry(PhantomData, PhantomData) +where + Deny: TryPass, + Allow: ShouldExecute; + +impl ShouldExecute for DenyThenTry +where + Deny: TryPass, + Allow: ShouldExecute, +{ + fn should_execute( + origin: &MultiLocation, + message: &mut Xcm, + max_weight: Weight, + weight_credit: &mut Weight, + ) -> Result<(), ()> { + Deny::try_pass(origin, message)?; + Allow::should_execute(origin, message, max_weight, weight_credit) + } +} + +// Allow xcm exchange only with locations in list +pub struct DenyExchangeWithUnknownLocation(PhantomData); +impl>> TryPass for DenyExchangeWithUnknownLocation { + fn try_pass(origin: &MultiLocation, message: &mut Xcm) -> Result<(), ()> { + let allowed_locations = T::get(); + + // Check if deposit or transfer belongs to allowed parachains + let mut allowed = allowed_locations.contains(origin); + + message.0.iter().for_each(|inst| match inst { + DepositReserveAsset { dest: dst, .. } => { + allowed |= allowed_locations.contains(dst); + } + TransferReserveAsset { dest: dst, .. } => { + allowed |= allowed_locations.contains(dst); + } + _ => {} + }); + + if allowed { + return Ok(()); + } + + log::warn!( + target: "xcm::barrier", + "Unexpected deposit or transfer location" + ); + // Deny + Err(()) + } +} + +pub type Weigher = FixedWeightBounds; + +pub struct XcmConfig(PhantomData); +impl Config for XcmConfig +where + T: pallet_configuration::Config, +{ + type Call = Call; + type XcmSender = XcmRouter; + // How to withdraw and deposit an asset. + type AssetTransactor = AssetTransactors; + type OriginConverter = XcmOriginToTransactDispatchOrigin; + type IsReserve = IsReserve; + type IsTeleporter = (); // Teleportation is disabled + type LocationInverter = LocationInverter; + type Barrier = Barrier; + type Weigher = Weigher; + type Trader = Trader; + 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; + type XcmRouter = XcmRouter; + type ExecuteXcmOrigin = EnsureXcmOrigin; + type XcmExecuteFilter = Everything; + type XcmExecutor = XcmExecutor>; + type XcmTeleportFilter = Everything; + type XcmReserveTransferFilter = Everything; + type Weigher = FixedWeightBounds; + type LocationInverter = LocationInverter; + 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>; +} + +impl cumulus_pallet_xcmp_queue::Config for Runtime { + type WeightInfo = (); + type Event = Event; + type XcmExecutor = XcmExecutor>; + type ChannelInfo = ParachainSystem; + type VersionWrapper = (); + type ExecuteOverweightOrigin = frame_system::EnsureRoot; + type ControllerOrigin = EnsureRoot; + type ControllerOriginConverter = XcmOriginToTransactDispatchOrigin; +} + +impl cumulus_pallet_dmp_queue::Config for Runtime { + type Event = Event; + type XcmExecutor = XcmExecutor>; + type ExecuteOverweightOrigin = frame_system::EnsureRoot; +} --- /dev/null +++ b/runtime/common/config/xcm/nativeassets.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 . + +use frame_support::{ + traits::{tokens::currency::Currency as CurrencyT, OnUnbalanced as OnUnbalancedT, Get}, + weights::{Weight, WeightToFeePolynomial}, +}; +use sp_runtime::traits::{CheckedConversion, Zero, Convert}; +use xcm::v1::{Junction::*, MultiLocation, Junctions::*}; +use xcm::latest::{ + AssetId::{Concrete}, + Fungibility::Fungible as XcmFungible, + MultiAsset, Error as XcmError, +}; +use xcm_builder::{CurrencyAdapter, NativeAsset}; +use xcm_executor::{ + Assets, + traits::{MatchesFungible, WeightTrader}, +}; +use pallet_foreign_assets::{AssetIds, NativeCurrency}; +use sp_std::marker::PhantomData; +use crate::{Balances, ParachainInfo}; +use super::{LocationToAccountId, RelayLocation}; + +use up_common::types::{AccountId, Balance}; + +pub struct OnlySelfCurrency; +impl> MatchesFungible for OnlySelfCurrency { + fn matches_fungible(a: &MultiAsset) -> Option { + let paraid = Parachain(ParachainInfo::parachain_id().into()); + match (&a.id, &a.fun) { + ( + Concrete(MultiLocation { + parents: 1, + interior: X1(loc), + }), + XcmFungible(ref amount), + ) if paraid == *loc => CheckedConversion::checked_from(*amount), + ( + Concrete(MultiLocation { + parents: 0, + interior: Here, + }), + 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. + (), +>; + +pub type AssetTransactors = LocalAssetTransactor; + +pub type IsReserve = NativeAsset; + +pub struct UsingOnlySelfCurrencyComponents< + WeightToFee: WeightToFeePolynomial, + AssetId: Get, + AccountId, + Currency: CurrencyT, + OnUnbalanced: OnUnbalancedT, +>( + Weight, + Currency::Balance, + PhantomData<(WeightToFee, AssetId, AccountId, Currency, OnUnbalanced)>, +); +impl< + WeightToFee: WeightToFeePolynomial, + AssetId: Get, + AccountId, + Currency: CurrencyT, + OnUnbalanced: OnUnbalancedT, + > WeightTrader + for UsingOnlySelfCurrencyComponents +{ + fn new() -> Self { + Self(0, Zero::zero(), PhantomData) + } + + fn buy_weight(&mut self, _weight: Weight, payment: Assets) -> Result { + Ok(payment) + } +} +impl< + WeightToFee: WeightToFeePolynomial, + AssetId: Get, + AccountId, + Currency: CurrencyT, + OnUnbalanced: OnUnbalancedT, + > Drop + for UsingOnlySelfCurrencyComponents +{ + fn drop(&mut self) { + OnUnbalanced::on_unbalanced(Currency::issue(self.1)); + } +} + +pub type Trader = UsingOnlySelfCurrencyComponents< + pallet_configuration::WeightToFee, + RelayLocation, + AccountId, + Balances, + (), +>; + +pub struct CurrencyIdConvert; +impl Convert> for CurrencyIdConvert { + fn convert(id: AssetIds) -> Option { + match id { + AssetIds::NativeAssetId(NativeCurrency::Here) => Some(MultiLocation::new( + 1, + X1(Parachain(ParachainInfo::get().into())), + )), + _ => None, + } + } +} --- a/runtime/common/construct_runtime/mod.rs +++ b/runtime/common/construct_runtime/mod.rs @@ -42,7 +42,9 @@ Treasury: pallet_treasury::{Pallet, Call, Storage, Config, Event} = 34, Sudo: pallet_sudo::{Pallet, Call, Storage, Config, Event} = 35, Vesting: orml_vesting::{Pallet, Storage, Call, Event, Config} = 37, - // Vesting: pallet_vesting::{Pallet, Call, Config, Storage, Event} = 37, + + XTokens: orml_xtokens = 38, + Tokens: orml_tokens = 39, // Contracts: pallet_contracts::{Pallet, Call, Storage, Event} = 38, // XCM helpers. @@ -80,6 +82,9 @@ #[runtimes(opal)] AppPromotion: pallet_app_promotion::{Pallet, Call, Storage, Event} = 73, + #[runtimes(opal)] + ForeignAssets: pallet_foreign_assets::{Pallet, Call, Storage, Event} = 80, + // Frontier EVM: pallet_evm::{Pallet, Config, Call, Storage, Event} = 100, Ethereum: pallet_ethereum::{Pallet, Config, Call, Storage, Event, Origin} = 101, --- a/runtime/common/mod.rs +++ b/runtime/common/mod.rs @@ -24,6 +24,9 @@ pub mod sponsoring; pub mod weights; +#[cfg(test)] +pub mod tests; + use sp_core::H160; use frame_support::traits::{Currency, OnUnbalanced, Imbalance}; use sp_runtime::{ --- a/runtime/common/runtime_apis.rs +++ b/runtime/common/runtime_apis.rs @@ -688,6 +688,10 @@ #[cfg(not(any(feature = "unique-runtime", feature = "quartz-runtime")))] list_benchmark!(list, extra, pallet_proxy_rmrk_equip, RmrkEquip); + #[cfg(not(any(feature = "unique-runtime", feature = "quartz-runtime")))] + list_benchmark!(list, extra, pallet_foreign_assets, ForeignAssets); + + // list_benchmark!(list, extra, pallet_evm_coder_substrate, EvmCoderSubstrate); let storage_info = AllPalletsReversedWithSystemFirst::storage_info(); @@ -744,6 +748,9 @@ #[cfg(not(any(feature = "unique-runtime", feature = "quartz-runtime")))] add_benchmark!(params, batches, pallet_proxy_rmrk_equip, RmrkEquip); + #[cfg(not(any(feature = "unique-runtime", feature = "quartz-runtime")))] + add_benchmark!(params, batches, pallet_foreign_assets, ForeignAssets); + // add_benchmark!(params, batches, pallet_evm_coder_substrate, EvmCoderSubstrate); if batches.is_empty() { return Err("Benchmark not found for this pallet.".into()) } --- /dev/null +++ b/runtime/common/tests/mod.rs @@ -0,0 +1,46 @@ +// 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 . + +use sp_runtime::BuildStorage; +use sp_core::{Public, Pair}; +use sp_std::vec; +use up_common::types::AuraId; +use crate::{GenesisConfig, ParachainInfoConfig, AuraConfig}; + +pub mod xcm; + +fn get_from_seed(seed: &str) -> ::Public { + TPublic::Pair::from_string(&format!("//{}", seed), None) + .expect("static values are valid; qed") + .public() +} + +fn new_test_ext(para_id: u32) -> sp_io::TestExternalities { + let cfg = GenesisConfig { + aura: AuraConfig { + authorities: vec![ + get_from_seed::("Alice"), + get_from_seed::("Bob"), + ], + }, + parachain_info: ParachainInfoConfig { + parachain_id: para_id.into(), + }, + ..GenesisConfig::default() + }; + + cfg.build_storage().unwrap().into() +} --- /dev/null +++ b/runtime/common/tests/xcm.rs @@ -0,0 +1,162 @@ +// 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 . + +use xcm_executor::traits::ShouldExecute; +use xcm::latest::prelude::*; +use logtest::Logger; +use crate::Call; +use super::new_test_ext; + +fn catch_xcm_barrier_log(logger: &mut Logger, expected_msg: &str) -> Result<(), String> { + for record in logger { + if record.target() == "xcm::barrier" && record.args() == expected_msg { + return Ok(()); + } + } + + Err(format!( + "the expected XCM barrier log `{}` is not found", + expected_msg + )) +} + +/// WARNING: Uses log capturing +/// See https://docs.rs/logtest/latest/logtest/index.html#constraints +pub fn barrier_denies_transact(logger: &mut Logger) { + let location = MultiLocation { + parents: 0, + interior: Junctions::Here, + }; + + // We will never decode this "call", + // so it is irrelevant what we are passing to the `transact` cmd. + let fake_encoded_call = vec![0u8]; + + let transact_inst = Transact { + origin_type: OriginKind::Superuser, + require_weight_at_most: 0, + call: fake_encoded_call.into(), + }; + + let mut xcm_program = Xcm::(vec![transact_inst]); + + let max_weight = 100_000; + let mut weight_credit = 100_000_000; + + let result = B::should_execute(&location, &mut xcm_program, max_weight, &mut weight_credit); + + assert!( + result.is_err(), + "the barrier should disallow the XCM transact cmd" + ); + + catch_xcm_barrier_log(logger, "transact XCM rejected").unwrap(); +} + +fn xcm_execute( + self_para_id: u32, + location: &MultiLocation, + xcm: &mut Xcm, +) -> Result<(), ()> { + new_test_ext(self_para_id).execute_with(|| { + let max_weight = 100_000; + let mut weight_credit = 100_000_000; + + B::should_execute(&location, xcm, max_weight, &mut weight_credit) + }) +} + +fn make_multiassets(location: &MultiLocation) -> MultiAssets { + let id = AssetId::Concrete(location.clone()); + let fun = Fungibility::Fungible(42); + let multiasset = MultiAsset { id, fun }; + + multiasset.into() +} + +fn make_transfer_reserve_asset(location: &MultiLocation) -> Xcm { + let assets = make_multiassets(location); + let inst = TransferReserveAsset { + assets, + dest: location.clone(), + xcm: Xcm(vec![]), + }; + + Xcm::(vec![inst]) +} + +fn make_deposit_reserve_asset(location: &MultiLocation) -> Xcm { + let assets = make_multiassets(location); + let inst = DepositReserveAsset { + assets: assets.into(), + max_assets: 42, + dest: location.clone(), + xcm: Xcm(vec![]), + }; + + Xcm::(vec![inst]) +} + +fn expect_transfer_location_denied( + logger: &mut Logger, + self_para_id: u32, + location: &MultiLocation, + xcm: &mut Xcm, +) -> Result<(), String> { + let result = xcm_execute::(self_para_id, location, xcm); + + if result.is_ok() { + return Err("the barrier should deny the unknown location".into()); + } + + catch_xcm_barrier_log(logger, "Unexpected deposit or transfer location") +} + +/// WARNING: Uses log capturing +/// See https://docs.rs/logtest/latest/logtest/index.html#constraints +pub fn barrier_denies_transfer_from_unknown_location( + logger: &mut Logger, + self_para_id: u32, +) -> Result<(), String> +where + B: ShouldExecute, +{ + const UNKNOWN_PARACHAIN_ID: u32 = 4057; + + let unknown_location = MultiLocation { + parents: 1, + interior: X1(Parachain(UNKNOWN_PARACHAIN_ID)), + }; + + let mut transfer_reserve_asset = make_transfer_reserve_asset(&unknown_location); + let mut deposit_reserve_asset = make_deposit_reserve_asset(&unknown_location); + + expect_transfer_location_denied::( + logger, + self_para_id, + &unknown_location, + &mut transfer_reserve_asset, + )?; + + expect_transfer_location_denied::( + logger, + self_para_id, + &unknown_location, + &mut deposit_reserve_asset, + )?; + + Ok(()) +} --- a/runtime/opal/Cargo.toml +++ b/runtime/opal/Cargo.toml @@ -35,6 +35,7 @@ 'pallet-nonfungible/runtime-benchmarks', 'pallet-proxy-rmrk-core/runtime-benchmarks', 'pallet-proxy-rmrk-equip/runtime-benchmarks', + 'pallet-foreign-assets/runtime-benchmarks', 'pallet-unique/runtime-benchmarks', 'pallet-inflation/runtime-benchmarks', 'pallet-app-promotion/runtime-benchmarks', @@ -123,13 +124,18 @@ 'up-sponsorship/std', "orml-vesting/std", + "orml-tokens/std", + "orml-xtokens/std", + "orml-traits/std", + "pallet-foreign-assets/std" ] limit-testing = ['pallet-unique/limit-testing', 'up-data-structs/limit-testing'] -opal-runtime = ['refungible', 'scheduler', 'rmrk', 'app-promotion'] +opal-runtime = ['refungible', 'scheduler', 'rmrk', 'app-promotion', 'foreign-assets'] refungible = [] scheduler = [] rmrk = [] +foreign-assets = [] app-promotion = [] ################################################################################ @@ -403,6 +409,24 @@ version = "0.4.1-dev" default-features = false +[dependencies.orml-xtokens] +git = "https://github.com/open-web3-stack/open-runtime-module-library" +branch = "polkadot-v0.9.27" +version = "0.4.1-dev" +default-features = false + +[dependencies.orml-tokens] +git = "https://github.com/open-web3-stack/open-runtime-module-library" +branch = "polkadot-v0.9.27" +version = "0.4.1-dev" +default-features = false + +[dependencies.orml-traits] +git = "https://github.com/open-web3-stack/open-runtime-module-library" +branch = "polkadot-v0.9.27" +version = "0.4.1-dev" +default-features = false + ################################################################################ # local dependencies @@ -442,7 +466,19 @@ fp-rpc = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27-fee-limit" } fp-self-contained = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27-fee-limit" } evm-coder = { default-features = false, path = '../../crates/evm-coder' } -up-sponsorship = { default-features = false, git = "https://github.com/uniquenetwork/pallet-sponsoring", branch = "polkadot-v0.9.27" } +up-sponsorship = { default-features = false, git = "https://github.com/uniquenetwork/pallet-sponsoring", branch = 'polkadot-v0.9.27' } +pallet-foreign-assets = { default-features = false, path = "../../pallets/foreign-assets" } + +################################################################################ +# Other Dependencies + +impl-trait-for-tuples = "0.2.2" + +################################################################################ +# Dev Dependencies + +[dev-dependencies.logtest] +version = "2.0.0" ################################################################################ # Build Dependencies --- a/runtime/opal/src/lib.rs +++ b/runtime/opal/src/lib.rs @@ -35,6 +35,11 @@ #[path = "../../common/mod.rs"] mod runtime_common; +pub mod xcm_barrier; + +#[cfg(test)] +mod tests; + pub use runtime_common::*; pub const RUNTIME_NAME: &str = "opal"; --- /dev/null +++ b/runtime/opal/src/tests/logcapture.rs @@ -0,0 +1,25 @@ +// 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 . + +use logtest::Logger; +use super::xcm::opal_xcm_tests; + +#[test] +fn opal_log_capture_tests() { + let mut logger = Logger::start(); + + opal_xcm_tests(&mut logger); +} --- /dev/null +++ b/runtime/opal/src/tests/mod.rs @@ -0,0 +1,18 @@ +// 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 . + +mod logcapture; +mod xcm; --- /dev/null +++ b/runtime/opal/src/tests/xcm.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 . + +use logtest::Logger; +use crate::{runtime_common::tests::xcm::*, xcm_barrier::Barrier}; + +const OPAL_PARA_ID: u32 = 2095; // Same as Quartz + +pub fn opal_xcm_tests(logger: &mut Logger) { + barrier_denies_transact::(logger); + + barrier_denies_transfer_from_unknown_location::(logger, OPAL_PARA_ID) + .expect_err("opal runtime allows any location"); +} --- /dev/null +++ b/runtime/opal/src/xcm_barrier.rs @@ -0,0 +1,48 @@ +// 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 . + +use frame_support::{weights::Weight, traits::Everything}; +use xcm::{latest::Xcm, v1::MultiLocation}; +use xcm_builder::{AllowTopLevelPaidExecutionFrom, TakeWeightCredit}; +use xcm_executor::traits::ShouldExecute; + +use crate::runtime_common::config::xcm::{DenyThenTry, DenyTransact}; + +/// Execution barrier that just takes `max_weight` from `weight_credit`. +/// +/// Useful to allow XCM execution by local chain users via extrinsics. +/// E.g. `pallet_xcm::reserve_asset_transfer` to transfer a reserve asset +/// out of the local chain to another one. +pub struct AllowAllDebug; +impl ShouldExecute for AllowAllDebug { + fn should_execute( + _origin: &MultiLocation, + _message: &mut Xcm, + _max_weight: Weight, + _weight_credit: &mut Weight, + ) -> Result<(), ()> { + Ok(()) + } +} + +pub type Barrier = DenyThenTry< + DenyTransact, + ( + TakeWeightCredit, + AllowTopLevelPaidExecutionFrom, + AllowAllDebug, + ), +>; --- a/runtime/quartz/Cargo.toml +++ b/runtime/quartz/Cargo.toml @@ -36,6 +36,7 @@ 'pallet-proxy-rmrk-core/runtime-benchmarks', 'pallet-proxy-rmrk-equip/runtime-benchmarks', 'pallet-unique/runtime-benchmarks', + 'pallet-foreign-assets/runtime-benchmarks', 'pallet-inflation/runtime-benchmarks', 'pallet-unique-scheduler/runtime-benchmarks', 'pallet-xcm/runtime-benchmarks', @@ -116,8 +117,15 @@ 'xcm-builder/std', 'xcm-executor/std', 'up-common/std', + 'rmrk-rpc/std', + 'evm-coder/std', + 'up-sponsorship/std', "orml-vesting/std", + "orml-tokens/std", + "orml-xtokens/std", + "orml-traits/std", + "pallet-foreign-assets/std" ] limit-testing = ['pallet-unique/limit-testing', 'up-data-structs/limit-testing'] quartz-runtime = ['refungible'] @@ -125,6 +133,7 @@ refungible = [] scheduler = [] rmrk = [] +foreign-assets = [] ################################################################################ # Substrate Dependencies @@ -397,6 +406,25 @@ version = "0.4.1-dev" default-features = false +[dependencies.orml-xtokens] +git = "https://github.com/open-web3-stack/open-runtime-module-library" +branch = "polkadot-v0.9.27" +version = "0.4.1-dev" +default-features = false + +[dependencies.orml-tokens] +git = "https://github.com/open-web3-stack/open-runtime-module-library" +branch = "polkadot-v0.9.27" +version = "0.4.1-dev" +default-features = false + +[dependencies.orml-traits] +git = "https://github.com/open-web3-stack/open-runtime-module-library" +branch = "polkadot-v0.9.27" +version = "0.4.1-dev" +default-features = false + + ################################################################################ # RMRK dependencies @@ -443,7 +471,19 @@ fp-rpc = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27-fee-limit" } fp-self-contained = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27-fee-limit" } evm-coder = { default-features = false, path = '../../crates/evm-coder' } -up-sponsorship = { default-features = false, git = "https://github.com/uniquenetwork/pallet-sponsoring", branch = "polkadot-v0.9.27" } +up-sponsorship = { default-features = false, git = "https://github.com/uniquenetwork/pallet-sponsoring", branch = 'polkadot-v0.9.27' } +pallet-foreign-assets = { default-features = false, path = "../../pallets/foreign-assets" } + +################################################################################ +# Other Dependencies + +impl-trait-for-tuples = "0.2.2" + +################################################################################ +# Dev Dependencies + +[dev-dependencies.logtest] +version = "2.0.0" ################################################################################ # Build Dependencies --- a/runtime/quartz/src/lib.rs +++ b/runtime/quartz/src/lib.rs @@ -35,6 +35,11 @@ #[path = "../../common/mod.rs"] mod runtime_common; +pub mod xcm_barrier; + +#[cfg(test)] +mod tests; + pub use runtime_common::*; pub const RUNTIME_NAME: &str = "quartz"; --- /dev/null +++ b/runtime/quartz/src/tests/logcapture.rs @@ -0,0 +1,25 @@ +// 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 . + +use logtest::Logger; +use super::xcm::quartz_xcm_tests; + +#[test] +fn quartz_log_capture_tests() { + let mut logger = Logger::start(); + + quartz_xcm_tests(&mut logger); +} --- /dev/null +++ b/runtime/quartz/src/tests/mod.rs @@ -0,0 +1,18 @@ +// 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 . + +mod logcapture; +mod xcm; --- /dev/null +++ b/runtime/quartz/src/tests/xcm.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 . + +use logtest::Logger; +use crate::{runtime_common::tests::xcm::*, xcm_barrier::Barrier}; + +const QUARTZ_PARA_ID: u32 = 2095; + +pub fn quartz_xcm_tests(logger: &mut Logger) { + barrier_denies_transact::(logger); + + barrier_denies_transfer_from_unknown_location::(logger, QUARTZ_PARA_ID) + .expect("quartz runtime denies an unknown location"); +} --- /dev/null +++ b/runtime/quartz/src/xcm_barrier.rs @@ -0,0 +1,83 @@ +// 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 . + +use frame_support::{ + match_types, parameter_types, + traits::{Get, Everything}, +}; +use sp_std::{vec, vec::Vec}; +use xcm::v1::{Junction::*, Junctions::*, MultiLocation}; +use xcm_builder::{ + AllowKnownQueryResponses, AllowSubscriptionsFrom, TakeWeightCredit, + AllowTopLevelPaidExecutionFrom, +}; + +use crate::{ + ParachainInfo, PolkadotXcm, + runtime_common::config::xcm::{DenyThenTry, DenyTransact, DenyExchangeWithUnknownLocation}, +}; + +match_types! { + pub type ParentOrSiblings: impl Contains = { + MultiLocation { parents: 1, interior: Here } | + MultiLocation { parents: 1, interior: X1(_) } + }; +} + +parameter_types! { + pub QuartzAllowedLocations: Vec = vec![ + // Self location + MultiLocation { + parents: 0, + interior: Here, + }, + // Parent location + MultiLocation { + parents: 1, + interior: Here, + }, + // Karura/Acala location + MultiLocation { + parents: 1, + interior: X1(Parachain(2000)), + }, + // Moonriver location + MultiLocation { + parents: 1, + interior: X1(Parachain(2023)), + }, + // Self parachain address + MultiLocation { + parents: 1, + interior: X1(Parachain(ParachainInfo::get().into())), + }, + ]; +} + +pub type Barrier = DenyThenTry< + ( + DenyTransact, + DenyExchangeWithUnknownLocation, + ), + ( + TakeWeightCredit, + AllowTopLevelPaidExecutionFrom, + // Expected responses are OK. + AllowKnownQueryResponses, + // Subscriptions for version tracking are OK. + AllowSubscriptionsFrom, + ), +>; --- a/runtime/unique/Cargo.toml +++ b/runtime/unique/Cargo.toml @@ -36,6 +36,7 @@ 'pallet-proxy-rmrk-core/runtime-benchmarks', 'pallet-proxy-rmrk-equip/runtime-benchmarks', 'pallet-unique/runtime-benchmarks', + 'pallet-foreign-assets/runtime-benchmarks', 'pallet-inflation/runtime-benchmarks', 'pallet-unique-scheduler/runtime-benchmarks', 'pallet-xcm/runtime-benchmarks', @@ -117,8 +118,15 @@ 'xcm-builder/std', 'xcm-executor/std', 'up-common/std', + 'rmrk-rpc/std', + 'evm-coder/std', + 'up-sponsorship/std', "orml-vesting/std", + "orml-tokens/std", + "orml-xtokens/std", + "orml-traits/std", + "pallet-foreign-assets/std" ] limit-testing = ['pallet-unique/limit-testing', 'up-data-structs/limit-testing'] unique-runtime = [] @@ -126,6 +134,7 @@ refungible = [] scheduler = [] rmrk = [] +foreign-assets = [] ################################################################################ # Substrate Dependencies @@ -398,6 +407,23 @@ version = "0.4.1-dev" default-features = false +[dependencies.orml-xtokens] +git = "https://github.com/open-web3-stack/open-runtime-module-library" +branch = "polkadot-v0.9.27" +version = "0.4.1-dev" +default-features = false + +[dependencies.orml-tokens] +git = "https://github.com/open-web3-stack/open-runtime-module-library" +branch = "polkadot-v0.9.27" +version = "0.4.1-dev" +default-features = false + +[dependencies.orml-traits] +git = "https://github.com/open-web3-stack/open-runtime-module-library" +branch = "polkadot-v0.9.27" +version = "0.4.1-dev" +default-features = false ################################################################################ # local dependencies @@ -437,7 +463,19 @@ fp-self-contained = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27-fee-limit" } fp-evm-mapping = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27-fee-limit" } evm-coder = { default-features = false, path = '../../crates/evm-coder' } -up-sponsorship = { default-features = false, git = "https://github.com/uniquenetwork/pallet-sponsoring", branch = "polkadot-v0.9.27" } +up-sponsorship = { default-features = false, git = "https://github.com/uniquenetwork/pallet-sponsoring", branch = 'polkadot-v0.9.27' } +pallet-foreign-assets = { default-features = false, path = "../../pallets/foreign-assets" } + +################################################################################ +# Other Dependencies + +impl-trait-for-tuples = "0.2.2" + +################################################################################ +# Dev Dependencies + +[dev-dependencies.logtest] +version = "2.0.0" ################################################################################ # Build Dependencies --- a/runtime/unique/src/lib.rs +++ b/runtime/unique/src/lib.rs @@ -35,6 +35,11 @@ #[path = "../../common/mod.rs"] mod runtime_common; +pub mod xcm_barrier; + +#[cfg(test)] +mod tests; + pub use runtime_common::*; pub const RUNTIME_NAME: &str = "unique"; --- /dev/null +++ b/runtime/unique/src/tests/logcapture.rs @@ -0,0 +1,25 @@ +// 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 . + +use logtest::Logger; +use super::xcm::unique_xcm_tests; + +#[test] +fn unique_log_capture_tests() { + let mut logger = Logger::start(); + + unique_xcm_tests(&mut logger); +} --- /dev/null +++ b/runtime/unique/src/tests/mod.rs @@ -0,0 +1,18 @@ +// 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 . + +mod logcapture; +mod xcm; --- /dev/null +++ b/runtime/unique/src/tests/xcm.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 . + +use logtest::Logger; +use crate::{runtime_common::tests::xcm::*, xcm_barrier::Barrier}; + +const UNIQUE_PARA_ID: u32 = 2037; + +pub fn unique_xcm_tests(logger: &mut Logger) { + barrier_denies_transact::(logger); + + barrier_denies_transfer_from_unknown_location::(logger, UNIQUE_PARA_ID) + .expect("unique runtime denies an unknown location"); +} --- /dev/null +++ b/runtime/unique/src/xcm_barrier.rs @@ -0,0 +1,83 @@ +// 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 . + +use frame_support::{ + match_types, parameter_types, + traits::{Get, Everything}, +}; +use sp_std::{vec, vec::Vec}; +use xcm::v1::{Junction::*, Junctions::*, MultiLocation}; +use xcm_builder::{ + AllowKnownQueryResponses, AllowSubscriptionsFrom, TakeWeightCredit, + AllowTopLevelPaidExecutionFrom, +}; + +use crate::{ + ParachainInfo, PolkadotXcm, + runtime_common::config::xcm::{DenyThenTry, DenyTransact, DenyExchangeWithUnknownLocation}, +}; + +match_types! { + pub type ParentOrSiblings: impl Contains = { + MultiLocation { parents: 1, interior: Here } | + MultiLocation { parents: 1, interior: X1(_) } + }; +} + +parameter_types! { + pub UniqueAllowedLocations: Vec = vec![ + // Self location + MultiLocation { + parents: 0, + interior: Here, + }, + // Parent location + MultiLocation { + parents: 1, + interior: Here, + }, + // Karura/Acala location + MultiLocation { + parents: 1, + interior: X1(Parachain(2000)), + }, + // Moonbeam location + MultiLocation { + parents: 1, + interior: X1(Parachain(2004)), + }, + // Self parachain address + MultiLocation { + parents: 1, + interior: X1(Parachain(ParachainInfo::get().into())), + }, + ]; +} + +pub type Barrier = DenyThenTry< + ( + DenyTransact, + DenyExchangeWithUnknownLocation, + ), + ( + TakeWeightCredit, + AllowTopLevelPaidExecutionFrom, + // Expected responses are OK. + AllowKnownQueryResponses, + // Subscriptions for version tracking are OK. + AllowSubscriptionsFrom, + ), +>; --- a/tests/package.json +++ b/tests/package.json @@ -77,7 +77,12 @@ "testInflation": "mocha --timeout 9999999 -r ts-node/register ./**/inflation.test.ts", "testScheduler": "mocha --timeout 9999999 -r ts-node/register ./**/scheduler.test.ts", "testSchedulingEVM": "mocha --timeout 9999999 -r ts-node/register ./**/eth/scheduling.test.ts", - "testXcmTransfer": "mocha --timeout 9999999 -r ts-node/register ./**/xcmTransfer.test.ts", + "testXcmUnique": "RUN_XCM_TESTS=1 mocha --timeout 9999999 -r ts-node/register ./**/xcm/xcmUnique.test.ts", + "testXcmQuartz": "RUN_XCM_TESTS=1 mocha --timeout 9999999 -r ts-node/register ./**/xcm/xcmQuartz.test.ts", + "testXcmOpal": "RUN_XCM_TESTS=1 mocha --timeout 9999999 -r ts-node/register ./**/xcm/xcmOpal.test.ts", + "testXcmTransferAcala": "mocha --timeout 9999999 -r ts-node/register ./**/xcm/xcmTransferAcala.test.ts acalaId=2000 uniqueId=5000", + "testXcmTransferStatemine": "mocha --timeout 9999999 -r ts-node/register ./**/xcm/xcmTransferStatemine.test.ts statemineId=1000 uniqueId=5000", + "testXcmTransferMoonbeam": "mocha --timeout 9999999 -r ts-node/register ./**/xcm/xcmTransferMoonbeam.test.ts", "testPalletPresence": "mocha --timeout 9999999 -r ts-node/register ./**/pallet-presence.test.ts", "testBlockProduction": "mocha --timeout 9999999 -r ts-node/register ./**/block-production.test.ts", "testEnableDisableTransfers": "mocha --timeout 9999999 -r ts-node/register ./**/enableDisableTransfer.test.ts", --- a/tests/scripts/readyness.js +++ b/tests/scripts/readyness.js @@ -1,7 +1,7 @@ const { ApiPromise, WsProvider } = require('@polkadot/api'); const connect = async () => { - const wsEndpoint = 'ws://127.0.0.1:9944' + const wsEndpoint = 'ws://127.0.0.1:9944'; const api = new ApiPromise({provider: new WsProvider(wsEndpoint)}); await api.isReadyOrError; @@ -12,10 +12,10 @@ } const sleep = time => { - return new Promise(resolve => { - setTimeout(() => resolve(), time); - }); -} + return new Promise(resolve => { + setTimeout(() => resolve(), time); + }); +}; const main = async () => { while(true) { --- a/tests/src/interfaces/augment-api-consts.ts +++ b/tests/src/interfaces/augment-api-consts.ts @@ -9,7 +9,7 @@ import type { Option, u128, u16, u32, u64, u8 } from '@polkadot/types-codec'; import type { Codec } from '@polkadot/types-codec/types'; import type { Perbill, Permill } from '@polkadot/types/interfaces/runtime'; -import type { FrameSupportPalletId, FrameSupportWeightsRuntimeDbWeight, FrameSystemLimitsBlockLength, FrameSystemLimitsBlockWeights, SpVersionRuntimeVersion } from '@polkadot/types/lookup'; +import type { FrameSupportPalletId, FrameSupportWeightsRuntimeDbWeight, FrameSystemLimitsBlockLength, FrameSystemLimitsBlockWeights, SpVersionRuntimeVersion, XcmV1MultiLocation } from '@polkadot/types/lookup'; export type __AugmentedConst = AugmentedConst; @@ -25,7 +25,7 @@ **/ nominal: u128 & AugmentedConst; /** - * The app's pallet id, used for deriving its sovereign account ID. + * The app's pallet id, used for deriving its sovereign account address. **/ palletId: FrameSupportPalletId & AugmentedConst; /** @@ -155,6 +155,17 @@ **/ [key: string]: Codec; }; + tokens: { + maxLocks: u32 & AugmentedConst; + /** + * The maximum number of named reserves that can exist on an account. + **/ + maxReserves: u32 & AugmentedConst; + /** + * Generic const + **/ + [key: string]: Codec; + }; transactionPayment: { /** * A fee mulitplier for `Operational` extrinsics to compute "virtual tip" to boost their @@ -232,5 +243,22 @@ **/ [key: string]: Codec; }; + xTokens: { + /** + * Base XCM weight. + * + * The actually weight for an XCM message is `T::BaseXcmWeight + + * T::Weigher::weight(&msg)`. + **/ + baseXcmWeight: u64 & AugmentedConst; + /** + * Self chain location. + **/ + selfLocation: XcmV1MultiLocation & AugmentedConst; + /** + * Generic const + **/ + [key: string]: Codec; + }; } // AugmentedConsts } // declare module --- a/tests/src/interfaces/augment-api-errors.ts +++ b/tests/src/interfaces/augment-api-errors.ts @@ -303,6 +303,10 @@ **/ NoPermission: AugmentedError; /** + * Number of methods that sponsored limit is defined for exceeds maximum. + **/ + TooManyMethodsHaveSponsoredLimit: AugmentedError; + /** * Generic error **/ [key: string]: AugmentedError; @@ -321,6 +325,29 @@ **/ [key: string]: AugmentedError; }; + foreignAssets: { + /** + * AssetId exists + **/ + AssetIdExisted: AugmentedError; + /** + * AssetId not exists + **/ + AssetIdNotExists: AugmentedError; + /** + * The given location could not be used (e.g. because it cannot be expressed in the + * desired version of XCM). + **/ + BadLocation: AugmentedError; + /** + * MultiLocation existed + **/ + MultiLocationExisted: AugmentedError; + /** + * Generic error + **/ + [key: string]: AugmentedError; + }; fungible: { /** * Fungible token does not support nesting. @@ -697,6 +724,41 @@ **/ [key: string]: AugmentedError; }; + tokens: { + /** + * Cannot convert Amount into Balance type + **/ + AmountIntoBalanceFailed: AugmentedError; + /** + * The balance is too low + **/ + BalanceTooLow: AugmentedError; + /** + * Beneficiary account must pre-exist + **/ + DeadAccount: AugmentedError; + /** + * Value too low to create account due to existential deposit + **/ + ExistentialDeposit: AugmentedError; + /** + * Transfer/payment would kill account + **/ + KeepAlive: AugmentedError; + /** + * Failed because liquidity restrictions due to locking + **/ + LiquidityRestrictions: AugmentedError; + /** + * Failed because the maximum locks was exceeded + **/ + MaxLocksExceeded: AugmentedError; + TooManyReserves: AugmentedError; + /** + * Generic error + **/ + [key: string]: AugmentedError; + }; treasury: { /** * The spend origin is valid but the amount it is allowed to spend is lower than the @@ -802,5 +864,90 @@ **/ [key: string]: AugmentedError; }; + xTokens: { + /** + * Asset has no reserve location. + **/ + AssetHasNoReserve: AugmentedError; + /** + * The specified index does not exist in a MultiAssets struct. + **/ + AssetIndexNonExistent: AugmentedError; + /** + * The version of the `Versioned` value used is not able to be + * interpreted. + **/ + BadVersion: AugmentedError; + /** + * Could not re-anchor the assets to declare the fees for the + * destination chain. + **/ + CannotReanchor: AugmentedError; + /** + * The destination `MultiLocation` provided cannot be inverted. + **/ + DestinationNotInvertible: AugmentedError; + /** + * We tried sending distinct asset and fee but they have different + * reserve chains. + **/ + DistinctReserveForAssetAndFee: AugmentedError; + /** + * Fee is not enough. + **/ + FeeNotEnough: AugmentedError; + /** + * Could not get ancestry of asset reserve location. + **/ + InvalidAncestry: AugmentedError; + /** + * The MultiAsset is invalid. + **/ + InvalidAsset: AugmentedError; + /** + * Invalid transfer destination. + **/ + InvalidDest: AugmentedError; + /** + * MinXcmFee not registered for certain reserve location + **/ + MinXcmFeeNotDefined: AugmentedError; + /** + * Not cross-chain transfer. + **/ + NotCrossChainTransfer: AugmentedError; + /** + * Currency is not cross-chain transferable. + **/ + NotCrossChainTransferableCurrency: AugmentedError; + /** + * Not supported MultiLocation + **/ + NotSupportedMultiLocation: AugmentedError; + /** + * The number of assets to be sent is over the maximum. + **/ + TooManyAssetsBeingSent: AugmentedError; + /** + * The message's weight could not be determined. + **/ + UnweighableMessage: AugmentedError; + /** + * XCM execution failed. + **/ + XcmExecutionFailed: AugmentedError; + /** + * The transfering asset amount is zero. + **/ + ZeroAmount: AugmentedError; + /** + * The fee is zero. + **/ + ZeroFee: AugmentedError; + /** + * Generic error + **/ + [key: string]: AugmentedError; + }; } // AugmentedErrors } // declare module --- a/tests/src/interfaces/augment-api-events.ts +++ b/tests/src/interfaces/augment-api-events.ts @@ -9,7 +9,7 @@ import type { Bytes, Null, Option, Result, U256, U8aFixed, bool, u128, u32, u64, u8 } from '@polkadot/types-codec'; import type { ITuple } from '@polkadot/types-codec/types'; import type { AccountId32, H160, H256 } from '@polkadot/types/interfaces/runtime'; -import type { EthereumLog, EvmCoreErrorExitReason, FrameSupportScheduleLookupError, FrameSupportTokensMiscBalanceStatus, FrameSupportWeightsDispatchInfo, OrmlVestingVestingSchedule, PalletEvmAccountBasicCrossAccountIdRepr, RmrkTraitsNftAccountIdOrCollectionNftTuple, SpRuntimeDispatchError, XcmV1MultiLocation, XcmV2Response, XcmV2TraitsError, XcmV2TraitsOutcome, XcmV2Xcm, XcmVersionedMultiAssets, XcmVersionedMultiLocation } from '@polkadot/types/lookup'; +import type { EthereumLog, EvmCoreErrorExitReason, FrameSupportScheduleLookupError, FrameSupportTokensMiscBalanceStatus, FrameSupportWeightsDispatchInfo, OrmlVestingVestingSchedule, PalletEvmAccountBasicCrossAccountIdRepr, PalletForeignAssetsAssetIds, PalletForeignAssetsModuleAssetMetadata, RmrkTraitsNftAccountIdOrCollectionNftTuple, SpRuntimeDispatchError, XcmV1MultiAsset, XcmV1MultiLocation, XcmV1MultiassetMultiAssets, XcmV2Response, XcmV2TraitsError, XcmV2TraitsOutcome, XcmV2Xcm, XcmVersionedMultiAssets, XcmVersionedMultiLocation } from '@polkadot/types/lookup'; export type __AugmentedEvent = AugmentedEvent; @@ -20,14 +20,14 @@ * The admin was set * * # Arguments - * * AccountId: ID of the admin + * * AccountId: account address of the admin **/ SetAdmin: AugmentedEvent; /** * Staking was performed * * # Arguments - * * AccountId: ID of the staker + * * AccountId: account of the staker * * Balance : staking amount **/ Stake: AugmentedEvent; @@ -35,7 +35,7 @@ * Staking recalculation was performed * * # Arguments - * * AccountId: ID of the staker. + * * AccountId: account of the staker. * * Balance : recalculation base * * Balance : total income **/ @@ -44,7 +44,7 @@ * Unstaking was performed * * # Arguments - * * AccountId: ID of the staker + * * AccountId: account of the staker * * Balance : unstaking amount **/ Unstake: AugmentedEvent; @@ -264,6 +264,28 @@ **/ [key: string]: AugmentedEvent; }; + foreignAssets: { + /** + * The asset registered. + **/ + AssetRegistered: AugmentedEvent; + /** + * The asset updated. + **/ + AssetUpdated: AugmentedEvent; + /** + * The foreign asset registered. + **/ + ForeignAssetRegistered: AugmentedEvent; + /** + * The foreign asset updated. + **/ + ForeignAssetUpdated: AugmentedEvent; + /** + * Generic event + **/ + [key: string]: AugmentedEvent; + }; parachainSystem: { /** * Downward messages were processed using the given weight. @@ -525,6 +547,66 @@ **/ [key: string]: AugmentedEvent; }; + tokens: { + /** + * A balance was set by root. + **/ + BalanceSet: AugmentedEvent; + /** + * Deposited some balance into an account + **/ + Deposited: AugmentedEvent; + /** + * An account was removed whose balance was non-zero but below + * ExistentialDeposit, resulting in an outright loss. + **/ + DustLost: AugmentedEvent; + /** + * An account was created with some free balance. + **/ + Endowed: AugmentedEvent; + /** + * Some locked funds were unlocked + **/ + LockRemoved: AugmentedEvent; + /** + * Some funds are locked + **/ + LockSet: AugmentedEvent; + /** + * Some balance was reserved (moved from free to reserved). + **/ + Reserved: AugmentedEvent; + /** + * Some reserved balance was repatriated (moved from reserved to + * another account). + **/ + ReserveRepatriated: AugmentedEvent; + /** + * Some balances were slashed (e.g. due to mis-behavior) + **/ + Slashed: AugmentedEvent; + /** + * The total issuance of an currency has been set + **/ + TotalIssuanceSet: AugmentedEvent; + /** + * Transfer succeeded. + **/ + Transfer: AugmentedEvent; + /** + * Some balance was unreserved (moved from reserved to free). + **/ + Unreserved: AugmentedEvent; + /** + * Some balances were withdrawn (e.g. pay for transaction fee) + **/ + Withdrawn: AugmentedEvent; + /** + * Generic event + **/ + [key: string]: AugmentedEvent; + }; transactionPayment: { /** * A transaction fee `actual_fee`, of which `tip` was added to the minimum inclusion fee, @@ -713,5 +795,15 @@ **/ [key: string]: AugmentedEvent; }; + xTokens: { + /** + * Transferred `MultiAsset` with fee. + **/ + TransferredMultiAssets: AugmentedEvent; + /** + * Generic event + **/ + [key: string]: AugmentedEvent; + }; } // AugmentedEvents } // declare module --- a/tests/src/interfaces/augment-api-query.ts +++ b/tests/src/interfaces/augment-api-query.ts @@ -9,7 +9,7 @@ import type { BTreeMap, Bytes, Option, U256, U8aFixed, Vec, bool, u128, u16, u32, u64, u8 } from '@polkadot/types-codec'; import type { AnyNumber, ITuple } from '@polkadot/types-codec/types'; import type { AccountId32, H160, H256 } from '@polkadot/types/interfaces/runtime'; -import type { CumulusPalletDmpQueueConfigData, CumulusPalletDmpQueuePageIndexData, CumulusPalletParachainSystemRelayStateSnapshotMessagingStateSnapshot, CumulusPalletXcmpQueueInboundChannelDetails, CumulusPalletXcmpQueueOutboundChannelDetails, CumulusPalletXcmpQueueQueueConfigData, EthereumBlock, EthereumLog, EthereumReceiptReceiptV3, EthereumTransactionTransactionV2, FpRpcTransactionStatus, FrameSupportWeightsPerDispatchClassU64, FrameSystemAccountInfo, FrameSystemEventRecord, FrameSystemLastRuntimeUpgradeInfo, FrameSystemPhase, OrmlVestingVestingSchedule, PalletBalancesAccountData, PalletBalancesBalanceLock, PalletBalancesReleases, PalletBalancesReserveData, PalletEvmAccountBasicCrossAccountIdRepr, PalletEvmContractHelpersSponsoringModeT, PalletNonfungibleItemData, PalletRefungibleItemData, PalletTransactionPaymentReleases, PalletTreasuryProposal, PalletUniqueSchedulerScheduledV3, PhantomTypeUpDataStructs, PolkadotCorePrimitivesOutboundHrmpMessage, PolkadotPrimitivesV2AbridgedHostConfiguration, PolkadotPrimitivesV2PersistedValidationData, PolkadotPrimitivesV2UpgradeRestriction, SpRuntimeDigest, SpTrieStorageProof, UpDataStructsCollection, UpDataStructsCollectionStats, UpDataStructsProperties, UpDataStructsPropertiesMapPropertyPermission, UpDataStructsPropertyPermission, UpDataStructsPropertyScope, UpDataStructsSponsorshipStateBasicCrossAccountIdRepr, UpDataStructsTokenChild } from '@polkadot/types/lookup'; +import type { CumulusPalletDmpQueueConfigData, CumulusPalletDmpQueuePageIndexData, CumulusPalletParachainSystemRelayStateSnapshotMessagingStateSnapshot, CumulusPalletXcmpQueueInboundChannelDetails, CumulusPalletXcmpQueueOutboundChannelDetails, CumulusPalletXcmpQueueQueueConfigData, EthereumBlock, EthereumLog, EthereumReceiptReceiptV3, EthereumTransactionTransactionV2, FpRpcTransactionStatus, FrameSupportWeightsPerDispatchClassU64, FrameSystemAccountInfo, FrameSystemEventRecord, FrameSystemLastRuntimeUpgradeInfo, FrameSystemPhase, OrmlTokensAccountData, OrmlTokensBalanceLock, OrmlTokensReserveData, OrmlVestingVestingSchedule, PalletBalancesAccountData, PalletBalancesBalanceLock, PalletBalancesReleases, PalletBalancesReserveData, PalletEvmAccountBasicCrossAccountIdRepr, PalletEvmContractHelpersSponsoringModeT, PalletForeignAssetsAssetIds, PalletForeignAssetsModuleAssetMetadata, PalletNonfungibleItemData, PalletRefungibleItemData, PalletTransactionPaymentReleases, PalletTreasuryProposal, PalletUniqueSchedulerScheduledV3, PhantomTypeUpDataStructs, PolkadotCorePrimitivesOutboundHrmpMessage, PolkadotPrimitivesV2AbridgedHostConfiguration, PolkadotPrimitivesV2PersistedValidationData, PolkadotPrimitivesV2UpgradeRestriction, SpRuntimeDigest, SpTrieStorageProof, UpDataStructsCollection, UpDataStructsCollectionStats, UpDataStructsProperties, UpDataStructsPropertiesMapPropertyPermission, UpDataStructsPropertyPermission, UpDataStructsPropertyScope, UpDataStructsSponsorshipStateBasicCrossAccountIdRepr, UpDataStructsTokenChild, XcmV1MultiLocation } from '@polkadot/types/lookup'; import type { Observable } from '@polkadot/types/types'; export type __AugmentedQuery = AugmentedQuery unknown>; @@ -18,21 +18,41 @@ declare module '@polkadot/api-base/types/storage' { interface AugmentedQueries { appPromotion: { + /** + * Stores the `admin` account. Some extrinsics can only be executed if they were signed by `admin`. + **/ admin: AugmentedQuery Observable>, []> & QueryableStorageEntry; /** * Stores a key for record for which the next revenue recalculation would be performed. * If `None`, then recalculation has not yet been performed or calculations have been completed for all stakers. **/ nextCalculatedRecord: AugmentedQuery Observable>>, []> & QueryableStorageEntry; + /** + * Stores amount of stakes for an `Account`. + * + * * **Key** - Staker account. + * * **Value** - Amount of stakes. + **/ pendingUnstake: AugmentedQuery Observable>>, [u32]> & QueryableStorageEntry; /** - * Amount of tokens staked by account in the blocknumber. + * Stores the amount of tokens staked by account in the blocknumber. + * + * * **Key1** - Staker account. + * * **Key2** - Relay block number when the stake was made. + * * **(Balance, BlockNumber)** - Balance of the stake. + * The number of the relay block in which we must perform the interest recalculation **/ staked: AugmentedQuery Observable>, [AccountId32, u32]> & QueryableStorageEntry; /** - * Amount of stakes for an Account + * Stores amount of stakes for an `Account`. + * + * * **Key** - Staker account. + * * **Value** - Amount of stakes. **/ stakesPerAccount: AugmentedQuery Observable, [AccountId32]> & QueryableStorageEntry; + /** + * Stores the total staked amount. + **/ totalStaked: AugmentedQuery Observable, []> & QueryableStorageEntry; /** * Generic query @@ -245,13 +265,6 @@ **/ owner: AugmentedQuery Observable, [H160]> & QueryableStorageEntry; selfSponsoring: AugmentedQuery Observable, [H160]> & QueryableStorageEntry; - /** - * Storage for last sponsored block. - * - * * **Key1** - contract address. - * * **Key2** - sponsored user address. - * * **Value** - last sponsored block number. - **/ sponsorBasket: AugmentedQuery Observable>, [H160, H160]> & QueryableStorageEntry; /** * Store for contract sponsorship state. @@ -261,6 +274,14 @@ **/ sponsoring: AugmentedQuery Observable, [H160]> & QueryableStorageEntry; /** + * Storage for last sponsored block. + * + * * **Key1** - contract address. + * * **Key2** - sponsored user address. + * * **Value** - last sponsored block number. + **/ + sponsoringFeeLimit: AugmentedQuery Observable>, [H160]> & QueryableStorageEntry; + /** * Store for sponsoring mode. * * ### Usage @@ -289,6 +310,41 @@ **/ [key: string]: QueryableStorageEntry; }; + foreignAssets: { + /** + * The storages for assets to fungible collection binding + * + **/ + assetBinding: AugmentedQuery Observable>, [u32]> & QueryableStorageEntry; + /** + * The storages for AssetMetadatas. + * + * AssetMetadatas: map AssetIds => Option + **/ + assetMetadatas: AugmentedQuery Observable>, [PalletForeignAssetsAssetIds]> & QueryableStorageEntry; + /** + * The storages for MultiLocations. + * + * ForeignAssetLocations: map ForeignAssetId => Option + **/ + foreignAssetLocations: AugmentedQuery Observable>, [u32]> & QueryableStorageEntry; + /** + * The storages for CurrencyIds. + * + * LocationToCurrencyIds: map MultiLocation => Option + **/ + locationToCurrencyIds: AugmentedQuery Observable>, [XcmV1MultiLocation]> & QueryableStorageEntry; + /** + * Next available Foreign AssetId ID. + * + * NextForeignAssetId: ForeignAssetId + **/ + nextForeignAssetId: AugmentedQuery Observable, []> & QueryableStorageEntry; + /** + * Generic query + **/ + [key: string]: QueryableStorageEntry; + }; fungible: { /** * Storage for assets delegated to a limited extent to other users. @@ -744,6 +800,34 @@ **/ [key: string]: QueryableStorageEntry; }; + tokens: { + /** + * The balance of a token type under an account. + * + * NOTE: If the total is ever zero, decrease account ref account. + * + * NOTE: This is only used in the case that this module is used to store + * balances. + **/ + accounts: AugmentedQuery Observable, [AccountId32, PalletForeignAssetsAssetIds]> & QueryableStorageEntry; + /** + * Any liquidity locks of a token type under an account. + * NOTE: Should only be accessed when setting, changing and freeing a lock. + **/ + locks: AugmentedQuery Observable>, [AccountId32, PalletForeignAssetsAssetIds]> & QueryableStorageEntry; + /** + * Named reserves on some account balances. + **/ + reserves: AugmentedQuery Observable>, [AccountId32, PalletForeignAssetsAssetIds]> & QueryableStorageEntry; + /** + * The total issuance of a token type. + **/ + totalIssuance: AugmentedQuery Observable, [PalletForeignAssetsAssetIds]> & QueryableStorageEntry; + /** + * Generic query + **/ + [key: string]: QueryableStorageEntry; + }; transactionPayment: { nextFeeMultiplier: AugmentedQuery Observable, []> & QueryableStorageEntry; storageVersion: AugmentedQuery Observable, []> & QueryableStorageEntry; --- a/tests/src/interfaces/augment-api-tx.ts +++ b/tests/src/interfaces/augment-api-tx.ts @@ -9,7 +9,7 @@ import type { Bytes, Compact, Option, U256, U8aFixed, Vec, bool, u128, u16, u32, u64, u8 } from '@polkadot/types-codec'; import type { AnyNumber, IMethod, ITuple } from '@polkadot/types-codec/types'; import type { AccountId32, Call, H160, H256, MultiAddress, Perbill, Permill } from '@polkadot/types/interfaces/runtime'; -import type { CumulusPrimitivesParachainInherentParachainInherentData, EthereumTransactionTransactionV2, FrameSupportScheduleMaybeHashed, OrmlVestingVestingSchedule, PalletEvmAccountBasicCrossAccountIdRepr, RmrkTraitsNftAccountIdOrCollectionNftTuple, RmrkTraitsPartEquippableList, RmrkTraitsPartPartType, RmrkTraitsResourceBasicResource, RmrkTraitsResourceComposableResource, RmrkTraitsResourceResourceTypes, RmrkTraitsResourceSlotResource, RmrkTraitsTheme, UpDataStructsCollectionLimits, UpDataStructsCollectionMode, UpDataStructsCollectionPermissions, UpDataStructsCreateCollectionData, UpDataStructsCreateItemData, UpDataStructsCreateItemExData, UpDataStructsProperty, UpDataStructsPropertyKeyPermission, XcmV1MultiLocation, XcmV2WeightLimit, XcmVersionedMultiAssets, XcmVersionedMultiLocation, XcmVersionedXcm } from '@polkadot/types/lookup'; +import type { CumulusPrimitivesParachainInherentParachainInherentData, EthereumTransactionTransactionV2, FrameSupportScheduleMaybeHashed, OrmlVestingVestingSchedule, PalletEvmAccountBasicCrossAccountIdRepr, PalletForeignAssetsAssetIds, PalletForeignAssetsModuleAssetMetadata, RmrkTraitsNftAccountIdOrCollectionNftTuple, RmrkTraitsPartEquippableList, RmrkTraitsPartPartType, RmrkTraitsResourceBasicResource, RmrkTraitsResourceComposableResource, RmrkTraitsResourceResourceTypes, RmrkTraitsResourceSlotResource, RmrkTraitsTheme, UpDataStructsCollectionLimits, UpDataStructsCollectionMode, UpDataStructsCollectionPermissions, UpDataStructsCreateCollectionData, UpDataStructsCreateItemData, UpDataStructsCreateItemExData, UpDataStructsProperty, UpDataStructsPropertyKeyPermission, XcmV1MultiLocation, XcmV2WeightLimit, XcmVersionedMultiAsset, XcmVersionedMultiAssets, XcmVersionedMultiLocation, XcmVersionedXcm } from '@polkadot/types/lookup'; export type __AugmentedSubmittable = AugmentedSubmittable<() => unknown>; export type __SubmittableExtrinsic = SubmittableExtrinsic; @@ -18,13 +18,101 @@ declare module '@polkadot/api-base/types/submittable' { interface AugmentedSubmittables { appPromotion: { + /** + * Recalculates interest for the specified number of stakers. + * If all stakers are not recalculated, the next call of the extrinsic + * will continue the recalculation, from those stakers for whom this + * was not perform in last call. + * + * # Permissions + * + * * Pallet admin + * + * # Arguments + * + * * `stakers_number`: the number of stakers for which recalculation will be performed + **/ payoutStakers: AugmentedSubmittable<(stakersNumber: Option | null | Uint8Array | u8 | AnyNumber) => SubmittableExtrinsic, [Option]>; + /** + * Sets an address as the the admin. + * + * # Permissions + * + * * Sudo + * + * # Arguments + * + * * `admin`: account of the new admin. + **/ setAdminAddress: AugmentedSubmittable<(admin: PalletEvmAccountBasicCrossAccountIdRepr | { Substrate: any } | { Ethereum: any } | string | Uint8Array) => SubmittableExtrinsic, [PalletEvmAccountBasicCrossAccountIdRepr]>; + /** + * Sets the pallet to be the sponsor for the collection. + * + * # Permissions + * + * * Pallet admin + * + * # Arguments + * + * * `collection_id`: ID of the collection that will be sponsored by `pallet_id` + **/ sponsorCollection: AugmentedSubmittable<(collectionId: u32 | AnyNumber | Uint8Array) => SubmittableExtrinsic, [u32]>; + /** + * Sets the pallet to be the sponsor for the contract. + * + * # Permissions + * + * * Pallet admin + * + * # Arguments + * + * * `contract_id`: the contract address that will be sponsored by `pallet_id` + **/ sponsorContract: AugmentedSubmittable<(contractId: H160 | string | Uint8Array) => SubmittableExtrinsic, [H160]>; + /** + * Stakes the amount of native tokens. + * Sets `amount` to the locked state. + * The maximum number of stakes for a staker is 10. + * + * # Arguments + * + * * `amount`: in native tokens. + **/ stake: AugmentedSubmittable<(amount: u128 | AnyNumber | Uint8Array) => SubmittableExtrinsic, [u128]>; + /** + * Removes the pallet as the sponsor for the collection. + * Returns [`NoPermission`][`Error::NoPermission`] + * if the pallet wasn't the sponsor. + * + * # Permissions + * + * * Pallet admin + * + * # Arguments + * + * * `collection_id`: ID of the collection that is sponsored by `pallet_id` + **/ stopSponsoringCollection: AugmentedSubmittable<(collectionId: u32 | AnyNumber | Uint8Array) => SubmittableExtrinsic, [u32]>; + /** + * Removes the pallet as the sponsor for the contract. + * Returns [`NoPermission`][`Error::NoPermission`] + * if the pallet wasn't the sponsor. + * + * # Permissions + * + * * Pallet admin + * + * # Arguments + * + * * `contract_id`: the contract address that is sponsored by `pallet_id` + **/ stopSponsoringContract: AugmentedSubmittable<(contractId: H160 | string | Uint8Array) => SubmittableExtrinsic, [H160]>; + /** + * Unstakes all stakes. + * Moves the sum of all stakes to the `reserved` state. + * After the end of `PendingInterval` this sum becomes completely + * free for further use. + **/ unstake: AugmentedSubmittable<() => SubmittableExtrinsic, []>; /** * Generic tx @@ -216,6 +304,14 @@ **/ [key: string]: SubmittableExtrinsicFunction; }; + foreignAssets: { + registerForeignAsset: AugmentedSubmittable<(owner: AccountId32 | string | Uint8Array, location: XcmVersionedMultiLocation | { V0: any } | { V1: any } | string | Uint8Array, metadata: PalletForeignAssetsModuleAssetMetadata | { name?: any; symbol?: any; decimals?: any; minimalBalance?: any } | string | Uint8Array) => SubmittableExtrinsic, [AccountId32, XcmVersionedMultiLocation, PalletForeignAssetsModuleAssetMetadata]>; + updateForeignAsset: AugmentedSubmittable<(foreignAssetId: u32 | AnyNumber | Uint8Array, location: XcmVersionedMultiLocation | { V0: any } | { V1: any } | string | Uint8Array, metadata: PalletForeignAssetsModuleAssetMetadata | { name?: any; symbol?: any; decimals?: any; minimalBalance?: any } | string | Uint8Array) => SubmittableExtrinsic, [u32, XcmVersionedMultiLocation, PalletForeignAssetsModuleAssetMetadata]>; + /** + * Generic tx + **/ + [key: string]: SubmittableExtrinsicFunction; + }; inflation: { /** * This method sets the inflation start date. Can be only called once. @@ -905,6 +1001,87 @@ **/ [key: string]: SubmittableExtrinsicFunction; }; + tokens: { + /** + * Exactly as `transfer`, except the origin must be root and the source + * account may be specified. + * + * The dispatch origin for this call must be _Root_. + * + * - `source`: The sender of the transfer. + * - `dest`: The recipient of the transfer. + * - `currency_id`: currency type. + * - `amount`: free balance amount to tranfer. + **/ + forceTransfer: AugmentedSubmittable<(source: MultiAddress | { Id: any } | { Index: any } | { Raw: any } | { Address32: any } | { Address20: any } | string | Uint8Array, dest: MultiAddress | { Id: any } | { Index: any } | { Raw: any } | { Address32: any } | { Address20: any } | string | Uint8Array, currencyId: PalletForeignAssetsAssetIds | { ForeignAssetId: any } | { NativeAssetId: any } | string | Uint8Array, amount: Compact | AnyNumber | Uint8Array) => SubmittableExtrinsic, [MultiAddress, MultiAddress, PalletForeignAssetsAssetIds, Compact]>; + /** + * Set the balances of a given account. + * + * This will alter `FreeBalance` and `ReservedBalance` in storage. it + * will also decrease the total issuance of the system + * (`TotalIssuance`). If the new free or reserved balance is below the + * existential deposit, it will reap the `AccountInfo`. + * + * The dispatch origin for this call is `root`. + **/ + setBalance: AugmentedSubmittable<(who: MultiAddress | { Id: any } | { Index: any } | { Raw: any } | { Address32: any } | { Address20: any } | string | Uint8Array, currencyId: PalletForeignAssetsAssetIds | { ForeignAssetId: any } | { NativeAssetId: any } | string | Uint8Array, newFree: Compact | AnyNumber | Uint8Array, newReserved: Compact | AnyNumber | Uint8Array) => SubmittableExtrinsic, [MultiAddress, PalletForeignAssetsAssetIds, Compact, Compact]>; + /** + * Transfer some liquid free balance to another account. + * + * `transfer` will set the `FreeBalance` of the sender and receiver. + * It will decrease the total issuance of the system by the + * `TransferFee`. If the sender's account is below the existential + * deposit as a result of the transfer, the account will be reaped. + * + * The dispatch origin for this call must be `Signed` by the + * transactor. + * + * - `dest`: The recipient of the transfer. + * - `currency_id`: currency type. + * - `amount`: free balance amount to tranfer. + **/ + transfer: AugmentedSubmittable<(dest: MultiAddress | { Id: any } | { Index: any } | { Raw: any } | { Address32: any } | { Address20: any } | string | Uint8Array, currencyId: PalletForeignAssetsAssetIds | { ForeignAssetId: any } | { NativeAssetId: any } | string | Uint8Array, amount: Compact | AnyNumber | Uint8Array) => SubmittableExtrinsic, [MultiAddress, PalletForeignAssetsAssetIds, Compact]>; + /** + * Transfer all remaining balance to the given account. + * + * NOTE: This function only attempts to transfer _transferable_ + * balances. This means that any locked, reserved, or existential + * deposits (when `keep_alive` is `true`), will not be transferred by + * this function. To ensure that this function results in a killed + * account, you might need to prepare the account by removing any + * reference counters, storage deposits, etc... + * + * The dispatch origin for this call must be `Signed` by the + * transactor. + * + * - `dest`: The recipient of the transfer. + * - `currency_id`: currency type. + * - `keep_alive`: A boolean to determine if the `transfer_all` + * operation should send all of the funds the account has, causing + * the sender account to be killed (false), or transfer everything + * except at least the existential deposit, which will guarantee to + * keep the sender account alive (true). + **/ + transferAll: AugmentedSubmittable<(dest: MultiAddress | { Id: any } | { Index: any } | { Raw: any } | { Address32: any } | { Address20: any } | string | Uint8Array, currencyId: PalletForeignAssetsAssetIds | { ForeignAssetId: any } | { NativeAssetId: any } | string | Uint8Array, keepAlive: bool | boolean | Uint8Array) => SubmittableExtrinsic, [MultiAddress, PalletForeignAssetsAssetIds, bool]>; + /** + * Same as the [`transfer`] call, but with a check that the transfer + * will not kill the origin account. + * + * 99% of the time you want [`transfer`] instead. + * + * The dispatch origin for this call must be `Signed` by the + * transactor. + * + * - `dest`: The recipient of the transfer. + * - `currency_id`: currency type. + * - `amount`: free balance amount to tranfer. + **/ + transferKeepAlive: AugmentedSubmittable<(dest: MultiAddress | { Id: any } | { Index: any } | { Raw: any } | { Address32: any } | { Address20: any } | string | Uint8Array, currencyId: PalletForeignAssetsAssetIds | { ForeignAssetId: any } | { NativeAssetId: any } | string | Uint8Array, amount: Compact | AnyNumber | Uint8Array) => SubmittableExtrinsic, [MultiAddress, PalletForeignAssetsAssetIds, Compact]>; + /** + * Generic tx + **/ + [key: string]: SubmittableExtrinsicFunction; + }; treasury: { /** * Approve a proposal. At a later time, the proposal will be allocated to the beneficiary @@ -1565,5 +1742,125 @@ **/ [key: string]: SubmittableExtrinsicFunction; }; + xTokens: { + /** + * Transfer native currencies. + * + * `dest_weight` is the weight for XCM execution on the dest chain, and + * it would be charged from the transferred assets. If set below + * requirements, the execution may fail and assets wouldn't be + * received. + * + * It's a no-op if any error on local XCM execution or message sending. + * Note sending assets out per se doesn't guarantee they would be + * received. Receiving depends on if the XCM message could be delivered + * by the network, and if the receiving chain would handle + * messages correctly. + **/ + transfer: AugmentedSubmittable<(currencyId: PalletForeignAssetsAssetIds | { ForeignAssetId: any } | { NativeAssetId: any } | string | Uint8Array, amount: u128 | AnyNumber | Uint8Array, dest: XcmVersionedMultiLocation | { V0: any } | { V1: any } | string | Uint8Array, destWeight: u64 | AnyNumber | Uint8Array) => SubmittableExtrinsic, [PalletForeignAssetsAssetIds, u128, XcmVersionedMultiLocation, u64]>; + /** + * Transfer `MultiAsset`. + * + * `dest_weight` is the weight for XCM execution on the dest chain, and + * it would be charged from the transferred assets. If set below + * requirements, the execution may fail and assets wouldn't be + * received. + * + * It's a no-op if any error on local XCM execution or message sending. + * Note sending assets out per se doesn't guarantee they would be + * received. Receiving depends on if the XCM message could be delivered + * by the network, and if the receiving chain would handle + * messages correctly. + **/ + transferMultiasset: AugmentedSubmittable<(asset: XcmVersionedMultiAsset | { V0: any } | { V1: any } | string | Uint8Array, dest: XcmVersionedMultiLocation | { V0: any } | { V1: any } | string | Uint8Array, destWeight: u64 | AnyNumber | Uint8Array) => SubmittableExtrinsic, [XcmVersionedMultiAsset, XcmVersionedMultiLocation, u64]>; + /** + * Transfer several `MultiAsset` specifying the item to be used as fee + * + * `dest_weight` is the weight for XCM execution on the dest chain, and + * it would be charged from the transferred assets. If set below + * requirements, the execution may fail and assets wouldn't be + * received. + * + * `fee_item` is index of the MultiAssets that we want to use for + * payment + * + * It's a no-op if any error on local XCM execution or message sending. + * Note sending assets out per se doesn't guarantee they would be + * received. Receiving depends on if the XCM message could be delivered + * by the network, and if the receiving chain would handle + * messages correctly. + **/ + transferMultiassets: AugmentedSubmittable<(assets: XcmVersionedMultiAssets | { V0: any } | { V1: any } | string | Uint8Array, feeItem: u32 | AnyNumber | Uint8Array, dest: XcmVersionedMultiLocation | { V0: any } | { V1: any } | string | Uint8Array, destWeight: u64 | AnyNumber | Uint8Array) => SubmittableExtrinsic, [XcmVersionedMultiAssets, u32, XcmVersionedMultiLocation, u64]>; + /** + * Transfer `MultiAsset` specifying the fee and amount as separate. + * + * `dest_weight` is the weight for XCM execution on the dest chain, and + * it would be charged from the transferred assets. If set below + * requirements, the execution may fail and assets wouldn't be + * received. + * + * `fee` is the multiasset to be spent to pay for execution in + * destination chain. Both fee and amount will be subtracted form the + * callers balance For now we only accept fee and asset having the same + * `MultiLocation` id. + * + * If `fee` is not high enough to cover for the execution costs in the + * destination chain, then the assets will be trapped in the + * destination chain + * + * It's a no-op if any error on local XCM execution or message sending. + * Note sending assets out per se doesn't guarantee they would be + * received. Receiving depends on if the XCM message could be delivered + * by the network, and if the receiving chain would handle + * messages correctly. + **/ + transferMultiassetWithFee: AugmentedSubmittable<(asset: XcmVersionedMultiAsset | { V0: any } | { V1: any } | string | Uint8Array, fee: XcmVersionedMultiAsset | { V0: any } | { V1: any } | string | Uint8Array, dest: XcmVersionedMultiLocation | { V0: any } | { V1: any } | string | Uint8Array, destWeight: u64 | AnyNumber | Uint8Array) => SubmittableExtrinsic, [XcmVersionedMultiAsset, XcmVersionedMultiAsset, XcmVersionedMultiLocation, u64]>; + /** + * Transfer several currencies specifying the item to be used as fee + * + * `dest_weight` is the weight for XCM execution on the dest chain, and + * it would be charged from the transferred assets. If set below + * requirements, the execution may fail and assets wouldn't be + * received. + * + * `fee_item` is index of the currencies tuple that we want to use for + * payment + * + * It's a no-op if any error on local XCM execution or message sending. + * Note sending assets out per se doesn't guarantee they would be + * received. Receiving depends on if the XCM message could be delivered + * by the network, and if the receiving chain would handle + * messages correctly. + **/ + transferMulticurrencies: AugmentedSubmittable<(currencies: Vec> | ([PalletForeignAssetsAssetIds | { ForeignAssetId: any } | { NativeAssetId: any } | string | Uint8Array, u128 | AnyNumber | Uint8Array])[], feeItem: u32 | AnyNumber | Uint8Array, dest: XcmVersionedMultiLocation | { V0: any } | { V1: any } | string | Uint8Array, destWeight: u64 | AnyNumber | Uint8Array) => SubmittableExtrinsic, [Vec>, u32, XcmVersionedMultiLocation, u64]>; + /** + * Transfer native currencies specifying the fee and amount as + * separate. + * + * `dest_weight` is the weight for XCM execution on the dest chain, and + * it would be charged from the transferred assets. If set below + * requirements, the execution may fail and assets wouldn't be + * received. + * + * `fee` is the amount to be spent to pay for execution in destination + * chain. Both fee and amount will be subtracted form the callers + * balance. + * + * If `fee` is not high enough to cover for the execution costs in the + * destination chain, then the assets will be trapped in the + * destination chain + * + * It's a no-op if any error on local XCM execution or message sending. + * Note sending assets out per se doesn't guarantee they would be + * received. Receiving depends on if the XCM message could be delivered + * by the network, and if the receiving chain would handle + * messages correctly. + **/ + transferWithFee: AugmentedSubmittable<(currencyId: PalletForeignAssetsAssetIds | { ForeignAssetId: any } | { NativeAssetId: any } | string | Uint8Array, amount: u128 | AnyNumber | Uint8Array, fee: u128 | AnyNumber | Uint8Array, dest: XcmVersionedMultiLocation | { V0: any } | { V1: any } | string | Uint8Array, destWeight: u64 | AnyNumber | Uint8Array) => SubmittableExtrinsic, [PalletForeignAssetsAssetIds, u128, u128, XcmVersionedMultiLocation, u64]>; + /** + * Generic tx + **/ + [key: string]: SubmittableExtrinsicFunction; + }; } // AugmentedSubmittables } // declare module --- a/tests/src/interfaces/augment-types.ts +++ b/tests/src/interfaces/augment-types.ts @@ -5,7 +5,7 @@ // this is required to allow for ambient/previous definitions import '@polkadot/types/types/registry'; -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, PalletAppPromotionCall, PalletAppPromotionError, PalletAppPromotionEvent, PalletBalancesAccountData, PalletBalancesBalanceLock, PalletBalancesCall, PalletBalancesError, PalletBalancesEvent, PalletBalancesReasons, PalletBalancesReleases, PalletBalancesReserveData, PalletCommonError, PalletCommonEvent, PalletConfigurationCall, PalletEthereumCall, PalletEthereumError, PalletEthereumEvent, PalletEthereumFakeTransactionFinalizer, PalletEthereumRawOrigin, PalletEvmAccountBasicCrossAccountIdRepr, PalletEvmCall, PalletEvmCoderSubstrateError, PalletEvmContractHelpersError, PalletEvmContractHelpersEvent, 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, PalletTransactionPaymentEvent, 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, UpDataStructsSponsorshipStateAccountId32, UpDataStructsSponsorshipStateBasicCrossAccountIdRepr, 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, OrmlTokensAccountData, OrmlTokensBalanceLock, OrmlTokensModuleCall, OrmlTokensModuleError, OrmlTokensModuleEvent, OrmlTokensReserveData, OrmlVestingModuleCall, OrmlVestingModuleError, OrmlVestingModuleEvent, OrmlVestingVestingSchedule, OrmlXtokensModuleCall, OrmlXtokensModuleError, OrmlXtokensModuleEvent, PalletAppPromotionCall, PalletAppPromotionError, PalletAppPromotionEvent, PalletBalancesAccountData, PalletBalancesBalanceLock, PalletBalancesCall, PalletBalancesError, PalletBalancesEvent, PalletBalancesReasons, PalletBalancesReleases, PalletBalancesReserveData, PalletCommonError, PalletCommonEvent, PalletConfigurationCall, PalletEthereumCall, PalletEthereumError, PalletEthereumEvent, PalletEthereumFakeTransactionFinalizer, PalletEthereumRawOrigin, PalletEvmAccountBasicCrossAccountIdRepr, PalletEvmCall, PalletEvmCoderSubstrateError, PalletEvmContractHelpersError, PalletEvmContractHelpersEvent, PalletEvmContractHelpersSponsoringModeT, PalletEvmError, PalletEvmEvent, PalletEvmMigrationCall, PalletEvmMigrationError, PalletForeignAssetsAssetIds, PalletForeignAssetsModuleAssetMetadata, PalletForeignAssetsModuleCall, PalletForeignAssetsModuleError, PalletForeignAssetsModuleEvent, PalletForeignAssetsNativeCurrency, PalletFungibleError, PalletInflationCall, PalletNonfungibleError, PalletNonfungibleItemData, PalletRefungibleError, PalletRefungibleItemData, PalletRmrkCoreCall, PalletRmrkCoreError, PalletRmrkCoreEvent, PalletRmrkEquipCall, PalletRmrkEquipError, PalletRmrkEquipEvent, PalletStructureCall, PalletStructureError, PalletStructureEvent, PalletSudoCall, PalletSudoError, PalletSudoEvent, PalletTemplateTransactionPaymentCall, PalletTemplateTransactionPaymentChargeTransactionPayment, PalletTimestampCall, PalletTransactionPaymentEvent, 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, UpDataStructsSponsorshipStateAccountId32, UpDataStructsSponsorshipStateBasicCrossAccountIdRepr, 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, XcmVersionedMultiAsset, XcmVersionedMultiAssets, XcmVersionedMultiLocation, XcmVersionedXcm } from './default'; import type { Data, StorageKey } from '@polkadot/types'; import type { BitVec, Bool, Bytes, F32, F64, I128, I16, I256, I32, I64, I8, Json, Null, OptionBool, Raw, Text, Type, U128, U16, U256, U32, U64, U8, USize, bool, f32, f64, 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'; @@ -790,10 +790,19 @@ OriginKindV0: OriginKindV0; OriginKindV1: OriginKindV1; OriginKindV2: OriginKindV2; + OrmlTokensAccountData: OrmlTokensAccountData; + OrmlTokensBalanceLock: OrmlTokensBalanceLock; + OrmlTokensModuleCall: OrmlTokensModuleCall; + OrmlTokensModuleError: OrmlTokensModuleError; + OrmlTokensModuleEvent: OrmlTokensModuleEvent; + OrmlTokensReserveData: OrmlTokensReserveData; OrmlVestingModuleCall: OrmlVestingModuleCall; OrmlVestingModuleError: OrmlVestingModuleError; OrmlVestingModuleEvent: OrmlVestingModuleEvent; OrmlVestingVestingSchedule: OrmlVestingVestingSchedule; + OrmlXtokensModuleCall: OrmlXtokensModuleCall; + OrmlXtokensModuleError: OrmlXtokensModuleError; + OrmlXtokensModuleEvent: OrmlXtokensModuleEvent; OutboundHrmpMessage: OutboundHrmpMessage; OutboundLaneData: OutboundLaneData; OutboundMessageFee: OutboundMessageFee; @@ -841,6 +850,12 @@ PalletEvmEvent: PalletEvmEvent; PalletEvmMigrationCall: PalletEvmMigrationCall; PalletEvmMigrationError: PalletEvmMigrationError; + PalletForeignAssetsAssetIds: PalletForeignAssetsAssetIds; + PalletForeignAssetsModuleAssetMetadata: PalletForeignAssetsModuleAssetMetadata; + PalletForeignAssetsModuleCall: PalletForeignAssetsModuleCall; + PalletForeignAssetsModuleError: PalletForeignAssetsModuleError; + PalletForeignAssetsModuleEvent: PalletForeignAssetsModuleEvent; + PalletForeignAssetsNativeCurrency: PalletForeignAssetsNativeCurrency; PalletFungibleError: PalletFungibleError; PalletId: PalletId; PalletInflationCall: PalletInflationCall; @@ -1422,6 +1437,7 @@ XcmV2WeightLimit: XcmV2WeightLimit; XcmV2Xcm: XcmV2Xcm; XcmVersion: XcmVersion; + XcmVersionedMultiAsset: XcmVersionedMultiAsset; XcmVersionedMultiAssets: XcmVersionedMultiAssets; XcmVersionedMultiLocation: XcmVersionedMultiLocation; XcmVersionedXcm: XcmVersionedXcm; --- a/tests/src/interfaces/default/types.ts +++ b/tests/src/interfaces/default/types.ts @@ -747,6 +747,163 @@ /** @name OpalRuntimeRuntime */ export interface OpalRuntimeRuntime extends Null {} +/** @name OrmlTokensAccountData */ +export interface OrmlTokensAccountData extends Struct { + readonly free: u128; + readonly reserved: u128; + readonly frozen: u128; +} + +/** @name OrmlTokensBalanceLock */ +export interface OrmlTokensBalanceLock extends Struct { + readonly id: U8aFixed; + readonly amount: u128; +} + +/** @name OrmlTokensModuleCall */ +export interface OrmlTokensModuleCall extends Enum { + readonly isTransfer: boolean; + readonly asTransfer: { + readonly dest: MultiAddress; + readonly currencyId: PalletForeignAssetsAssetIds; + readonly amount: Compact; + } & Struct; + readonly isTransferAll: boolean; + readonly asTransferAll: { + readonly dest: MultiAddress; + readonly currencyId: PalletForeignAssetsAssetIds; + readonly keepAlive: bool; + } & Struct; + readonly isTransferKeepAlive: boolean; + readonly asTransferKeepAlive: { + readonly dest: MultiAddress; + readonly currencyId: PalletForeignAssetsAssetIds; + readonly amount: Compact; + } & Struct; + readonly isForceTransfer: boolean; + readonly asForceTransfer: { + readonly source: MultiAddress; + readonly dest: MultiAddress; + readonly currencyId: PalletForeignAssetsAssetIds; + readonly amount: Compact; + } & Struct; + readonly isSetBalance: boolean; + readonly asSetBalance: { + readonly who: MultiAddress; + readonly currencyId: PalletForeignAssetsAssetIds; + readonly newFree: Compact; + readonly newReserved: Compact; + } & Struct; + readonly type: 'Transfer' | 'TransferAll' | 'TransferKeepAlive' | 'ForceTransfer' | 'SetBalance'; +} + +/** @name OrmlTokensModuleError */ +export interface OrmlTokensModuleError extends Enum { + readonly isBalanceTooLow: boolean; + readonly isAmountIntoBalanceFailed: boolean; + readonly isLiquidityRestrictions: boolean; + readonly isMaxLocksExceeded: boolean; + readonly isKeepAlive: boolean; + readonly isExistentialDeposit: boolean; + readonly isDeadAccount: boolean; + readonly isTooManyReserves: boolean; + readonly type: 'BalanceTooLow' | 'AmountIntoBalanceFailed' | 'LiquidityRestrictions' | 'MaxLocksExceeded' | 'KeepAlive' | 'ExistentialDeposit' | 'DeadAccount' | 'TooManyReserves'; +} + +/** @name OrmlTokensModuleEvent */ +export interface OrmlTokensModuleEvent extends Enum { + readonly isEndowed: boolean; + readonly asEndowed: { + readonly currencyId: PalletForeignAssetsAssetIds; + readonly who: AccountId32; + readonly amount: u128; + } & Struct; + readonly isDustLost: boolean; + readonly asDustLost: { + readonly currencyId: PalletForeignAssetsAssetIds; + readonly who: AccountId32; + readonly amount: u128; + } & Struct; + readonly isTransfer: boolean; + readonly asTransfer: { + readonly currencyId: PalletForeignAssetsAssetIds; + readonly from: AccountId32; + readonly to: AccountId32; + readonly amount: u128; + } & Struct; + readonly isReserved: boolean; + readonly asReserved: { + readonly currencyId: PalletForeignAssetsAssetIds; + readonly who: AccountId32; + readonly amount: u128; + } & Struct; + readonly isUnreserved: boolean; + readonly asUnreserved: { + readonly currencyId: PalletForeignAssetsAssetIds; + readonly who: AccountId32; + readonly amount: u128; + } & Struct; + readonly isReserveRepatriated: boolean; + readonly asReserveRepatriated: { + readonly currencyId: PalletForeignAssetsAssetIds; + readonly from: AccountId32; + readonly to: AccountId32; + readonly amount: u128; + readonly status: FrameSupportTokensMiscBalanceStatus; + } & Struct; + readonly isBalanceSet: boolean; + readonly asBalanceSet: { + readonly currencyId: PalletForeignAssetsAssetIds; + readonly who: AccountId32; + readonly free: u128; + readonly reserved: u128; + } & Struct; + readonly isTotalIssuanceSet: boolean; + readonly asTotalIssuanceSet: { + readonly currencyId: PalletForeignAssetsAssetIds; + readonly amount: u128; + } & Struct; + readonly isWithdrawn: boolean; + readonly asWithdrawn: { + readonly currencyId: PalletForeignAssetsAssetIds; + readonly who: AccountId32; + readonly amount: u128; + } & Struct; + readonly isSlashed: boolean; + readonly asSlashed: { + readonly currencyId: PalletForeignAssetsAssetIds; + readonly who: AccountId32; + readonly freeAmount: u128; + readonly reservedAmount: u128; + } & Struct; + readonly isDeposited: boolean; + readonly asDeposited: { + readonly currencyId: PalletForeignAssetsAssetIds; + readonly who: AccountId32; + readonly amount: u128; + } & Struct; + readonly isLockSet: boolean; + readonly asLockSet: { + readonly lockId: U8aFixed; + readonly currencyId: PalletForeignAssetsAssetIds; + readonly who: AccountId32; + readonly amount: u128; + } & Struct; + readonly isLockRemoved: boolean; + readonly asLockRemoved: { + readonly lockId: U8aFixed; + readonly currencyId: PalletForeignAssetsAssetIds; + readonly who: AccountId32; + } & Struct; + readonly type: 'Endowed' | 'DustLost' | 'Transfer' | 'Reserved' | 'Unreserved' | 'ReserveRepatriated' | 'BalanceSet' | 'TotalIssuanceSet' | 'Withdrawn' | 'Slashed' | 'Deposited' | 'LockSet' | 'LockRemoved'; +} + +/** @name OrmlTokensReserveData */ +export interface OrmlTokensReserveData extends Struct { + readonly id: Null; + readonly amount: u128; +} + /** @name OrmlVestingModuleCall */ export interface OrmlVestingModuleCall extends Enum { readonly isClaim: boolean; @@ -806,6 +963,89 @@ readonly perPeriod: Compact; } +/** @name OrmlXtokensModuleCall */ +export interface OrmlXtokensModuleCall extends Enum { + readonly isTransfer: boolean; + readonly asTransfer: { + readonly currencyId: PalletForeignAssetsAssetIds; + readonly amount: u128; + readonly dest: XcmVersionedMultiLocation; + readonly destWeight: u64; + } & Struct; + readonly isTransferMultiasset: boolean; + readonly asTransferMultiasset: { + readonly asset: XcmVersionedMultiAsset; + readonly dest: XcmVersionedMultiLocation; + readonly destWeight: u64; + } & Struct; + readonly isTransferWithFee: boolean; + readonly asTransferWithFee: { + readonly currencyId: PalletForeignAssetsAssetIds; + readonly amount: u128; + readonly fee: u128; + readonly dest: XcmVersionedMultiLocation; + readonly destWeight: u64; + } & Struct; + readonly isTransferMultiassetWithFee: boolean; + readonly asTransferMultiassetWithFee: { + readonly asset: XcmVersionedMultiAsset; + readonly fee: XcmVersionedMultiAsset; + readonly dest: XcmVersionedMultiLocation; + readonly destWeight: u64; + } & Struct; + readonly isTransferMulticurrencies: boolean; + readonly asTransferMulticurrencies: { + readonly currencies: Vec>; + readonly feeItem: u32; + readonly dest: XcmVersionedMultiLocation; + readonly destWeight: u64; + } & Struct; + readonly isTransferMultiassets: boolean; + readonly asTransferMultiassets: { + readonly assets: XcmVersionedMultiAssets; + readonly feeItem: u32; + readonly dest: XcmVersionedMultiLocation; + readonly destWeight: u64; + } & Struct; + readonly type: 'Transfer' | 'TransferMultiasset' | 'TransferWithFee' | 'TransferMultiassetWithFee' | 'TransferMulticurrencies' | 'TransferMultiassets'; +} + +/** @name OrmlXtokensModuleError */ +export interface OrmlXtokensModuleError extends Enum { + readonly isAssetHasNoReserve: boolean; + readonly isNotCrossChainTransfer: boolean; + readonly isInvalidDest: boolean; + readonly isNotCrossChainTransferableCurrency: boolean; + readonly isUnweighableMessage: boolean; + readonly isXcmExecutionFailed: boolean; + readonly isCannotReanchor: boolean; + readonly isInvalidAncestry: boolean; + readonly isInvalidAsset: boolean; + readonly isDestinationNotInvertible: boolean; + readonly isBadVersion: boolean; + readonly isDistinctReserveForAssetAndFee: boolean; + readonly isZeroFee: boolean; + readonly isZeroAmount: boolean; + readonly isTooManyAssetsBeingSent: boolean; + readonly isAssetIndexNonExistent: boolean; + readonly isFeeNotEnough: boolean; + readonly isNotSupportedMultiLocation: boolean; + readonly isMinXcmFeeNotDefined: boolean; + readonly type: 'AssetHasNoReserve' | 'NotCrossChainTransfer' | 'InvalidDest' | 'NotCrossChainTransferableCurrency' | 'UnweighableMessage' | 'XcmExecutionFailed' | 'CannotReanchor' | 'InvalidAncestry' | 'InvalidAsset' | 'DestinationNotInvertible' | 'BadVersion' | 'DistinctReserveForAssetAndFee' | 'ZeroFee' | 'ZeroAmount' | 'TooManyAssetsBeingSent' | 'AssetIndexNonExistent' | 'FeeNotEnough' | 'NotSupportedMultiLocation' | 'MinXcmFeeNotDefined'; +} + +/** @name OrmlXtokensModuleEvent */ +export interface OrmlXtokensModuleEvent extends Enum { + readonly isTransferredMultiAssets: boolean; + readonly asTransferredMultiAssets: { + readonly sender: AccountId32; + readonly assets: XcmV1MultiassetMultiAssets; + readonly fee: XcmV1MultiAsset; + readonly dest: XcmV1MultiLocation; + } & Struct; + readonly type: 'TransferredMultiAssets'; +} + /** @name PalletAppPromotionCall */ export interface PalletAppPromotionCall extends Enum { readonly isSetAdminAddress: boolean; @@ -1186,7 +1426,8 @@ export interface PalletEvmContractHelpersError extends Enum { readonly isNoPermission: boolean; readonly isNoPendingSponsor: boolean; - readonly type: 'NoPermission' | 'NoPendingSponsor'; + readonly isTooManyMethodsHaveSponsoredLimit: boolean; + readonly type: 'NoPermission' | 'NoPendingSponsor' | 'TooManyMethodsHaveSponsoredLimit'; } /** @name PalletEvmContractHelpersEvent */ @@ -1264,6 +1505,83 @@ readonly type: 'AccountNotEmpty' | 'AccountIsNotMigrating'; } +/** @name PalletForeignAssetsAssetIds */ +export interface PalletForeignAssetsAssetIds extends Enum { + readonly isForeignAssetId: boolean; + readonly asForeignAssetId: u32; + readonly isNativeAssetId: boolean; + readonly asNativeAssetId: PalletForeignAssetsNativeCurrency; + readonly type: 'ForeignAssetId' | 'NativeAssetId'; +} + +/** @name PalletForeignAssetsModuleAssetMetadata */ +export interface PalletForeignAssetsModuleAssetMetadata extends Struct { + readonly name: Bytes; + readonly symbol: Bytes; + readonly decimals: u8; + readonly minimalBalance: u128; +} + +/** @name PalletForeignAssetsModuleCall */ +export interface PalletForeignAssetsModuleCall extends Enum { + readonly isRegisterForeignAsset: boolean; + readonly asRegisterForeignAsset: { + readonly owner: AccountId32; + readonly location: XcmVersionedMultiLocation; + readonly metadata: PalletForeignAssetsModuleAssetMetadata; + } & Struct; + readonly isUpdateForeignAsset: boolean; + readonly asUpdateForeignAsset: { + readonly foreignAssetId: u32; + readonly location: XcmVersionedMultiLocation; + readonly metadata: PalletForeignAssetsModuleAssetMetadata; + } & Struct; + readonly type: 'RegisterForeignAsset' | 'UpdateForeignAsset'; +} + +/** @name PalletForeignAssetsModuleError */ +export interface PalletForeignAssetsModuleError extends Enum { + readonly isBadLocation: boolean; + readonly isMultiLocationExisted: boolean; + readonly isAssetIdNotExists: boolean; + readonly isAssetIdExisted: boolean; + readonly type: 'BadLocation' | 'MultiLocationExisted' | 'AssetIdNotExists' | 'AssetIdExisted'; +} + +/** @name PalletForeignAssetsModuleEvent */ +export interface PalletForeignAssetsModuleEvent extends Enum { + readonly isForeignAssetRegistered: boolean; + readonly asForeignAssetRegistered: { + readonly assetId: u32; + readonly assetAddress: XcmV1MultiLocation; + readonly metadata: PalletForeignAssetsModuleAssetMetadata; + } & Struct; + readonly isForeignAssetUpdated: boolean; + readonly asForeignAssetUpdated: { + readonly assetId: u32; + readonly assetAddress: XcmV1MultiLocation; + readonly metadata: PalletForeignAssetsModuleAssetMetadata; + } & Struct; + readonly isAssetRegistered: boolean; + readonly asAssetRegistered: { + readonly assetId: PalletForeignAssetsAssetIds; + readonly metadata: PalletForeignAssetsModuleAssetMetadata; + } & Struct; + readonly isAssetUpdated: boolean; + readonly asAssetUpdated: { + readonly assetId: PalletForeignAssetsAssetIds; + readonly metadata: PalletForeignAssetsModuleAssetMetadata; + } & Struct; + readonly type: 'ForeignAssetRegistered' | 'ForeignAssetUpdated' | 'AssetRegistered' | 'AssetUpdated'; +} + +/** @name PalletForeignAssetsNativeCurrency */ +export interface PalletForeignAssetsNativeCurrency extends Enum { + readonly isHere: boolean; + readonly isParent: boolean; + readonly type: 'Here' | 'Parent'; +} + /** @name PalletFungibleError */ export interface PalletFungibleError extends Enum { readonly isNotFungibleDataUsedToMintFungibleCollectionToken: boolean; @@ -2492,7 +2810,7 @@ readonly sponsorship: UpDataStructsSponsorshipStateAccountId32; readonly limits: UpDataStructsCollectionLimits; readonly permissions: UpDataStructsCollectionPermissions; - readonly externalCollection: bool; + readonly flags: U8aFixed; } /** @name UpDataStructsCollectionLimits */ @@ -2666,6 +2984,7 @@ readonly tokenPropertyPermissions: Vec; readonly properties: Vec; readonly readOnly: bool; + readonly foreign: bool; } /** @name UpDataStructsSponsoringRateLimit */ @@ -3441,6 +3760,15 @@ /** @name XcmV2Xcm */ export interface XcmV2Xcm extends Vec {} +/** @name XcmVersionedMultiAsset */ +export interface XcmVersionedMultiAsset extends Enum { + readonly isV0: boolean; + readonly asV0: XcmV0MultiAsset; + readonly isV1: boolean; + readonly asV1: XcmV1MultiAsset; + readonly type: 'V0' | 'V1'; +} + /** @name XcmVersionedMultiAssets */ export interface XcmVersionedMultiAssets extends Enum { readonly isV0: boolean; --- a/tests/src/interfaces/lookup.ts +++ b/tests/src/interfaces/lookup.ts @@ -323,118 +323,47 @@ perPeriod: 'Compact' }, /** - * Lookup39: cumulus_pallet_xcmp_queue::pallet::Event + * Lookup39: orml_xtokens::module::Event **/ - CumulusPalletXcmpQueueEvent: { + OrmlXtokensModuleEvent: { _enum: { - Success: { - messageHash: 'Option', - weight: 'u64', - }, - Fail: { - messageHash: 'Option', - error: 'XcmV2TraitsError', - weight: 'u64', - }, - BadVersion: { - messageHash: 'Option', - }, - BadFormat: { - messageHash: 'Option', - }, - UpwardMessageSent: { - messageHash: 'Option', - }, - XcmpMessageSent: { - messageHash: 'Option', - }, - OverweightEnqueued: { - sender: 'u32', - sentAt: 'u32', - index: 'u64', - required: 'u64', - }, - OverweightServiced: { - index: 'u64', - used: 'u64' + TransferredMultiAssets: { + sender: 'AccountId32', + assets: 'XcmV1MultiassetMultiAssets', + fee: 'XcmV1MultiAsset', + dest: 'XcmV1MultiLocation' } } }, /** - * Lookup41: xcm::v2::traits::Error + * Lookup40: xcm::v1::multiasset::MultiAssets **/ - XcmV2TraitsError: { - _enum: { - Overflow: 'Null', - Unimplemented: 'Null', - UntrustedReserveLocation: 'Null', - UntrustedTeleportLocation: 'Null', - MultiLocationFull: 'Null', - MultiLocationNotInvertible: 'Null', - BadOrigin: 'Null', - InvalidLocation: 'Null', - AssetNotFound: 'Null', - FailedToTransactAsset: 'Null', - NotWithdrawable: 'Null', - LocationCannotHold: 'Null', - ExceedsMaxMessageSize: 'Null', - DestinationUnsupported: 'Null', - Transport: 'Null', - Unroutable: 'Null', - UnknownClaim: 'Null', - FailedToDecode: 'Null', - MaxWeightInvalid: 'Null', - NotHoldingFees: 'Null', - TooExpensive: 'Null', - Trap: 'u64', - UnhandledXcmVersion: 'Null', - WeightLimitReached: 'u64', - Barrier: 'Null', - WeightNotComputable: 'Null' - } - }, + XcmV1MultiassetMultiAssets: 'Vec', /** - * Lookup43: pallet_xcm::pallet::Event + * Lookup42: xcm::v1::multiasset::MultiAsset **/ - PalletXcmEvent: { - _enum: { - Attempted: 'XcmV2TraitsOutcome', - Sent: '(XcmV1MultiLocation,XcmV1MultiLocation,XcmV2Xcm)', - UnexpectedResponse: '(XcmV1MultiLocation,u64)', - ResponseReady: '(u64,XcmV2Response)', - Notified: '(u64,u8,u8)', - NotifyOverweight: '(u64,u8,u8,u64,u64)', - NotifyDispatchError: '(u64,u8,u8)', - NotifyDecodeFailed: '(u64,u8,u8)', - InvalidResponder: '(XcmV1MultiLocation,u64,Option)', - InvalidResponderVersion: '(XcmV1MultiLocation,u64)', - ResponseTaken: 'u64', - AssetsTrapped: '(H256,XcmV1MultiLocation,XcmVersionedMultiAssets)', - VersionChangeNotified: '(XcmV1MultiLocation,u32)', - SupportedVersionChanged: '(XcmV1MultiLocation,u32)', - NotifyTargetSendFail: '(XcmV1MultiLocation,u64,XcmV2TraitsError)', - NotifyTargetMigrationFail: '(XcmVersionedMultiLocation,u64)' - } + XcmV1MultiAsset: { + id: 'XcmV1MultiassetAssetId', + fun: 'XcmV1MultiassetFungibility' }, /** - * Lookup44: xcm::v2::traits::Outcome + * Lookup43: xcm::v1::multiasset::AssetId **/ - XcmV2TraitsOutcome: { + XcmV1MultiassetAssetId: { _enum: { - Complete: 'u64', - Incomplete: '(u64,XcmV2TraitsError)', - Error: 'XcmV2TraitsError' + Concrete: 'XcmV1MultiLocation', + Abstract: 'Bytes' } }, /** - * Lookup45: xcm::v1::multilocation::MultiLocation + * Lookup44: xcm::v1::multilocation::MultiLocation **/ XcmV1MultiLocation: { parents: 'u8', interior: 'XcmV1MultilocationJunctions' }, /** - * Lookup46: xcm::v1::multilocation::Junctions + * Lookup45: xcm::v1::multilocation::Junctions **/ XcmV1MultilocationJunctions: { _enum: { @@ -450,7 +379,7 @@ } }, /** - * Lookup47: xcm::v1::junction::Junction + * Lookup46: xcm::v1::junction::Junction **/ XcmV1Junction: { _enum: { @@ -478,7 +407,7 @@ } }, /** - * Lookup49: xcm::v0::junction::NetworkId + * Lookup48: xcm::v0::junction::NetworkId **/ XcmV0JunctionNetworkId: { _enum: { @@ -489,7 +418,7 @@ } }, /** - * Lookup53: xcm::v0::junction::BodyId + * Lookup52: xcm::v0::junction::BodyId **/ XcmV0JunctionBodyId: { _enum: { @@ -503,7 +432,7 @@ } }, /** - * Lookup54: xcm::v0::junction::BodyPart + * Lookup53: xcm::v0::junction::BodyPart **/ XcmV0JunctionBodyPart: { _enum: { @@ -526,11 +455,230 @@ } }, /** - * Lookup55: xcm::v2::Xcm + * Lookup54: xcm::v1::multiasset::Fungibility + **/ + XcmV1MultiassetFungibility: { + _enum: { + Fungible: 'Compact', + NonFungible: 'XcmV1MultiassetAssetInstance' + } + }, + /** + * Lookup55: xcm::v1::multiasset::AssetInstance + **/ + XcmV1MultiassetAssetInstance: { + _enum: { + Undefined: 'Null', + Index: 'Compact', + Array4: '[u8;4]', + Array8: '[u8;8]', + Array16: '[u8;16]', + Array32: '[u8;32]', + Blob: 'Bytes' + } + }, + /** + * Lookup58: orml_tokens::module::Event + **/ + OrmlTokensModuleEvent: { + _enum: { + Endowed: { + currencyId: 'PalletForeignAssetsAssetIds', + who: 'AccountId32', + amount: 'u128', + }, + DustLost: { + currencyId: 'PalletForeignAssetsAssetIds', + who: 'AccountId32', + amount: 'u128', + }, + Transfer: { + currencyId: 'PalletForeignAssetsAssetIds', + from: 'AccountId32', + to: 'AccountId32', + amount: 'u128', + }, + Reserved: { + currencyId: 'PalletForeignAssetsAssetIds', + who: 'AccountId32', + amount: 'u128', + }, + Unreserved: { + currencyId: 'PalletForeignAssetsAssetIds', + who: 'AccountId32', + amount: 'u128', + }, + ReserveRepatriated: { + currencyId: 'PalletForeignAssetsAssetIds', + from: 'AccountId32', + to: 'AccountId32', + amount: 'u128', + status: 'FrameSupportTokensMiscBalanceStatus', + }, + BalanceSet: { + currencyId: 'PalletForeignAssetsAssetIds', + who: 'AccountId32', + free: 'u128', + reserved: 'u128', + }, + TotalIssuanceSet: { + currencyId: 'PalletForeignAssetsAssetIds', + amount: 'u128', + }, + Withdrawn: { + currencyId: 'PalletForeignAssetsAssetIds', + who: 'AccountId32', + amount: 'u128', + }, + Slashed: { + currencyId: 'PalletForeignAssetsAssetIds', + who: 'AccountId32', + freeAmount: 'u128', + reservedAmount: 'u128', + }, + Deposited: { + currencyId: 'PalletForeignAssetsAssetIds', + who: 'AccountId32', + amount: 'u128', + }, + LockSet: { + lockId: '[u8;8]', + currencyId: 'PalletForeignAssetsAssetIds', + who: 'AccountId32', + amount: 'u128', + }, + LockRemoved: { + lockId: '[u8;8]', + currencyId: 'PalletForeignAssetsAssetIds', + who: 'AccountId32' + } + } + }, + /** + * Lookup59: pallet_foreign_assets::AssetIds + **/ + PalletForeignAssetsAssetIds: { + _enum: { + ForeignAssetId: 'u32', + NativeAssetId: 'PalletForeignAssetsNativeCurrency' + } + }, + /** + * Lookup60: pallet_foreign_assets::NativeCurrency + **/ + PalletForeignAssetsNativeCurrency: { + _enum: ['Here', 'Parent'] + }, + /** + * Lookup61: cumulus_pallet_xcmp_queue::pallet::Event + **/ + CumulusPalletXcmpQueueEvent: { + _enum: { + Success: { + messageHash: 'Option', + weight: 'u64', + }, + Fail: { + messageHash: 'Option', + error: 'XcmV2TraitsError', + weight: 'u64', + }, + BadVersion: { + messageHash: 'Option', + }, + BadFormat: { + messageHash: 'Option', + }, + UpwardMessageSent: { + messageHash: 'Option', + }, + XcmpMessageSent: { + messageHash: 'Option', + }, + OverweightEnqueued: { + sender: 'u32', + sentAt: 'u32', + index: 'u64', + required: 'u64', + }, + OverweightServiced: { + index: 'u64', + used: 'u64' + } + } + }, + /** + * Lookup63: xcm::v2::traits::Error + **/ + XcmV2TraitsError: { + _enum: { + Overflow: 'Null', + Unimplemented: 'Null', + UntrustedReserveLocation: 'Null', + UntrustedTeleportLocation: 'Null', + MultiLocationFull: 'Null', + MultiLocationNotInvertible: 'Null', + BadOrigin: 'Null', + InvalidLocation: 'Null', + AssetNotFound: 'Null', + FailedToTransactAsset: 'Null', + NotWithdrawable: 'Null', + LocationCannotHold: 'Null', + ExceedsMaxMessageSize: 'Null', + DestinationUnsupported: 'Null', + Transport: 'Null', + Unroutable: 'Null', + UnknownClaim: 'Null', + FailedToDecode: 'Null', + MaxWeightInvalid: 'Null', + NotHoldingFees: 'Null', + TooExpensive: 'Null', + Trap: 'u64', + UnhandledXcmVersion: 'Null', + WeightLimitReached: 'u64', + Barrier: 'Null', + WeightNotComputable: 'Null' + } + }, + /** + * Lookup65: pallet_xcm::pallet::Event **/ + PalletXcmEvent: { + _enum: { + Attempted: 'XcmV2TraitsOutcome', + Sent: '(XcmV1MultiLocation,XcmV1MultiLocation,XcmV2Xcm)', + UnexpectedResponse: '(XcmV1MultiLocation,u64)', + ResponseReady: '(u64,XcmV2Response)', + Notified: '(u64,u8,u8)', + NotifyOverweight: '(u64,u8,u8,u64,u64)', + NotifyDispatchError: '(u64,u8,u8)', + NotifyDecodeFailed: '(u64,u8,u8)', + InvalidResponder: '(XcmV1MultiLocation,u64,Option)', + InvalidResponderVersion: '(XcmV1MultiLocation,u64)', + ResponseTaken: 'u64', + AssetsTrapped: '(H256,XcmV1MultiLocation,XcmVersionedMultiAssets)', + VersionChangeNotified: '(XcmV1MultiLocation,u32)', + SupportedVersionChanged: '(XcmV1MultiLocation,u32)', + NotifyTargetSendFail: '(XcmV1MultiLocation,u64,XcmV2TraitsError)', + NotifyTargetMigrationFail: '(XcmVersionedMultiLocation,u64)' + } + }, + /** + * Lookup66: xcm::v2::traits::Outcome + **/ + XcmV2TraitsOutcome: { + _enum: { + Complete: 'u64', + Incomplete: '(u64,XcmV2TraitsError)', + Error: 'XcmV2TraitsError' + } + }, + /** + * Lookup67: xcm::v2::Xcm + **/ XcmV2Xcm: 'Vec', /** - * Lookup57: xcm::v2::Instruction + * Lookup69: xcm::v2::Instruction **/ XcmV2Instruction: { _enum: { @@ -625,53 +773,10 @@ maxResponseWeight: 'Compact', }, UnsubscribeVersion: 'Null' - } - }, - /** - * Lookup58: xcm::v1::multiasset::MultiAssets - **/ - XcmV1MultiassetMultiAssets: 'Vec', - /** - * Lookup60: xcm::v1::multiasset::MultiAsset - **/ - XcmV1MultiAsset: { - id: 'XcmV1MultiassetAssetId', - fun: 'XcmV1MultiassetFungibility' - }, - /** - * Lookup61: xcm::v1::multiasset::AssetId - **/ - XcmV1MultiassetAssetId: { - _enum: { - Concrete: 'XcmV1MultiLocation', - Abstract: 'Bytes' } }, /** - * Lookup62: xcm::v1::multiasset::Fungibility - **/ - XcmV1MultiassetFungibility: { - _enum: { - Fungible: 'Compact', - NonFungible: 'XcmV1MultiassetAssetInstance' - } - }, - /** - * Lookup63: xcm::v1::multiasset::AssetInstance - **/ - XcmV1MultiassetAssetInstance: { - _enum: { - Undefined: 'Null', - Index: 'Compact', - Array4: '[u8;4]', - Array8: '[u8;8]', - Array16: '[u8;16]', - Array32: '[u8;32]', - Blob: 'Bytes' - } - }, - /** - * Lookup66: xcm::v2::Response + * Lookup70: xcm::v2::Response **/ XcmV2Response: { _enum: { @@ -682,19 +787,19 @@ } }, /** - * Lookup69: xcm::v0::OriginKind + * Lookup73: xcm::v0::OriginKind **/ XcmV0OriginKind: { _enum: ['Native', 'SovereignAccount', 'Superuser', 'Xcm'] }, /** - * Lookup70: xcm::double_encoded::DoubleEncoded + * Lookup74: xcm::double_encoded::DoubleEncoded **/ XcmDoubleEncoded: { encoded: 'Bytes' }, /** - * Lookup71: xcm::v1::multiasset::MultiAssetFilter + * Lookup75: xcm::v1::multiasset::MultiAssetFilter **/ XcmV1MultiassetMultiAssetFilter: { _enum: { @@ -703,7 +808,7 @@ } }, /** - * Lookup72: xcm::v1::multiasset::WildMultiAsset + * Lookup76: xcm::v1::multiasset::WildMultiAsset **/ XcmV1MultiassetWildMultiAsset: { _enum: { @@ -715,13 +820,13 @@ } }, /** - * Lookup73: xcm::v1::multiasset::WildFungibility + * Lookup77: xcm::v1::multiasset::WildFungibility **/ XcmV1MultiassetWildFungibility: { _enum: ['Fungible', 'NonFungible'] }, /** - * Lookup74: xcm::v2::WeightLimit + * Lookup78: xcm::v2::WeightLimit **/ XcmV2WeightLimit: { _enum: { @@ -730,7 +835,7 @@ } }, /** - * Lookup76: xcm::VersionedMultiAssets + * Lookup80: xcm::VersionedMultiAssets **/ XcmVersionedMultiAssets: { _enum: { @@ -739,7 +844,7 @@ } }, /** - * Lookup78: xcm::v0::multi_asset::MultiAsset + * Lookup82: xcm::v0::multi_asset::MultiAsset **/ XcmV0MultiAsset: { _enum: { @@ -778,7 +883,7 @@ } }, /** - * Lookup79: xcm::v0::multi_location::MultiLocation + * Lookup83: xcm::v0::multi_location::MultiLocation **/ XcmV0MultiLocation: { _enum: { @@ -794,7 +899,7 @@ } }, /** - * Lookup80: xcm::v0::junction::Junction + * Lookup84: xcm::v0::junction::Junction **/ XcmV0Junction: { _enum: { @@ -823,7 +928,7 @@ } }, /** - * Lookup81: xcm::VersionedMultiLocation + * Lookup85: xcm::VersionedMultiLocation **/ XcmVersionedMultiLocation: { _enum: { @@ -832,7 +937,7 @@ } }, /** - * Lookup82: cumulus_pallet_xcm::pallet::Event + * Lookup86: cumulus_pallet_xcm::pallet::Event **/ CumulusPalletXcmEvent: { _enum: { @@ -842,7 +947,7 @@ } }, /** - * Lookup83: cumulus_pallet_dmp_queue::pallet::Event + * Lookup87: cumulus_pallet_dmp_queue::pallet::Event **/ CumulusPalletDmpQueueEvent: { _enum: { @@ -873,7 +978,7 @@ } }, /** - * Lookup84: pallet_unique::RawEvent> + * Lookup88: pallet_unique::RawEvent> **/ PalletUniqueRawEvent: { _enum: { @@ -890,7 +995,7 @@ } }, /** - * Lookup85: pallet_evm::account::BasicCrossAccountIdRepr + * Lookup89: pallet_evm::account::BasicCrossAccountIdRepr **/ PalletEvmAccountBasicCrossAccountIdRepr: { _enum: { @@ -899,7 +1004,7 @@ } }, /** - * Lookup88: pallet_unique_scheduler::pallet::Event + * Lookup92: pallet_unique_scheduler::pallet::Event **/ PalletUniqueSchedulerEvent: { _enum: { @@ -924,13 +1029,13 @@ } }, /** - * Lookup91: frame_support::traits::schedule::LookupError + * Lookup95: frame_support::traits::schedule::LookupError **/ FrameSupportScheduleLookupError: { _enum: ['Unknown', 'BadFormat'] }, /** - * Lookup92: pallet_common::pallet::Event + * Lookup96: pallet_common::pallet::Event **/ PalletCommonEvent: { _enum: { @@ -948,7 +1053,7 @@ } }, /** - * Lookup95: pallet_structure::pallet::Event + * Lookup99: pallet_structure::pallet::Event **/ PalletStructureEvent: { _enum: { @@ -956,7 +1061,7 @@ } }, /** - * Lookup96: pallet_rmrk_core::pallet::Event + * Lookup100: pallet_rmrk_core::pallet::Event **/ PalletRmrkCoreEvent: { _enum: { @@ -1033,7 +1138,7 @@ } }, /** - * Lookup97: rmrk_traits::nft::AccountIdOrCollectionNftTuple + * Lookup101: rmrk_traits::nft::AccountIdOrCollectionNftTuple **/ RmrkTraitsNftAccountIdOrCollectionNftTuple: { _enum: { @@ -1042,7 +1147,7 @@ } }, /** - * Lookup102: pallet_rmrk_equip::pallet::Event + * Lookup106: pallet_rmrk_equip::pallet::Event **/ PalletRmrkEquipEvent: { _enum: { @@ -1057,7 +1162,7 @@ } }, /** - * Lookup103: pallet_app_promotion::pallet::Event + * Lookup107: pallet_app_promotion::pallet::Event **/ PalletAppPromotionEvent: { _enum: { @@ -1068,8 +1173,42 @@ } }, /** - * Lookup104: pallet_evm::pallet::Event + * Lookup108: pallet_foreign_assets::module::Event **/ + PalletForeignAssetsModuleEvent: { + _enum: { + ForeignAssetRegistered: { + assetId: 'u32', + assetAddress: 'XcmV1MultiLocation', + metadata: 'PalletForeignAssetsModuleAssetMetadata', + }, + ForeignAssetUpdated: { + assetId: 'u32', + assetAddress: 'XcmV1MultiLocation', + metadata: 'PalletForeignAssetsModuleAssetMetadata', + }, + AssetRegistered: { + assetId: 'PalletForeignAssetsAssetIds', + metadata: 'PalletForeignAssetsModuleAssetMetadata', + }, + AssetUpdated: { + assetId: 'PalletForeignAssetsAssetIds', + metadata: 'PalletForeignAssetsModuleAssetMetadata' + } + } + }, + /** + * Lookup109: pallet_foreign_assets::module::AssetMetadata + **/ + PalletForeignAssetsModuleAssetMetadata: { + name: 'Bytes', + symbol: 'Bytes', + decimals: 'u8', + minimalBalance: 'u128' + }, + /** + * Lookup110: pallet_evm::pallet::Event + **/ PalletEvmEvent: { _enum: { Log: 'EthereumLog', @@ -1082,7 +1221,7 @@ } }, /** - * Lookup105: ethereum::log::Log + * Lookup111: ethereum::log::Log **/ EthereumLog: { address: 'H160', @@ -1090,7 +1229,7 @@ data: 'Bytes' }, /** - * Lookup109: pallet_ethereum::pallet::Event + * Lookup115: pallet_ethereum::pallet::Event **/ PalletEthereumEvent: { _enum: { @@ -1098,7 +1237,7 @@ } }, /** - * Lookup110: evm_core::error::ExitReason + * Lookup116: evm_core::error::ExitReason **/ EvmCoreErrorExitReason: { _enum: { @@ -1109,13 +1248,13 @@ } }, /** - * Lookup111: evm_core::error::ExitSucceed + * Lookup117: evm_core::error::ExitSucceed **/ EvmCoreErrorExitSucceed: { _enum: ['Stopped', 'Returned', 'Suicided'] }, /** - * Lookup112: evm_core::error::ExitError + * Lookup118: evm_core::error::ExitError **/ EvmCoreErrorExitError: { _enum: { @@ -1137,13 +1276,13 @@ } }, /** - * Lookup115: evm_core::error::ExitRevert + * Lookup121: evm_core::error::ExitRevert **/ EvmCoreErrorExitRevert: { _enum: ['Reverted'] }, /** - * Lookup116: evm_core::error::ExitFatal + * Lookup122: evm_core::error::ExitFatal **/ EvmCoreErrorExitFatal: { _enum: { @@ -1154,7 +1293,7 @@ } }, /** - * Lookup117: pallet_evm_contract_helpers::pallet::Event + * Lookup123: pallet_evm_contract_helpers::pallet::Event **/ PalletEvmContractHelpersEvent: { _enum: { @@ -1164,7 +1303,7 @@ } }, /** - * Lookup118: frame_system::Phase + * Lookup124: frame_system::Phase **/ FrameSystemPhase: { _enum: { @@ -1174,14 +1313,14 @@ } }, /** - * Lookup120: frame_system::LastRuntimeUpgradeInfo + * Lookup126: frame_system::LastRuntimeUpgradeInfo **/ FrameSystemLastRuntimeUpgradeInfo: { specVersion: 'Compact', specName: 'Text' }, /** - * Lookup121: frame_system::pallet::Call + * Lookup127: frame_system::pallet::Call **/ FrameSystemCall: { _enum: { @@ -1219,7 +1358,7 @@ } }, /** - * Lookup126: frame_system::limits::BlockWeights + * Lookup132: frame_system::limits::BlockWeights **/ FrameSystemLimitsBlockWeights: { baseBlock: 'u64', @@ -1227,7 +1366,7 @@ perClass: 'FrameSupportWeightsPerDispatchClassWeightsPerClass' }, /** - * Lookup127: frame_support::weights::PerDispatchClass + * Lookup133: frame_support::weights::PerDispatchClass **/ FrameSupportWeightsPerDispatchClassWeightsPerClass: { normal: 'FrameSystemLimitsWeightsPerClass', @@ -1235,7 +1374,7 @@ mandatory: 'FrameSystemLimitsWeightsPerClass' }, /** - * Lookup128: frame_system::limits::WeightsPerClass + * Lookup134: frame_system::limits::WeightsPerClass **/ FrameSystemLimitsWeightsPerClass: { baseExtrinsic: 'u64', @@ -1244,13 +1383,13 @@ reserved: 'Option' }, /** - * Lookup130: frame_system::limits::BlockLength + * Lookup136: frame_system::limits::BlockLength **/ FrameSystemLimitsBlockLength: { max: 'FrameSupportWeightsPerDispatchClassU32' }, /** - * Lookup131: frame_support::weights::PerDispatchClass + * Lookup137: frame_support::weights::PerDispatchClass **/ FrameSupportWeightsPerDispatchClassU32: { normal: 'u32', @@ -1258,14 +1397,14 @@ mandatory: 'u32' }, /** - * Lookup132: frame_support::weights::RuntimeDbWeight + * Lookup138: frame_support::weights::RuntimeDbWeight **/ FrameSupportWeightsRuntimeDbWeight: { read: 'u64', write: 'u64' }, /** - * Lookup133: sp_version::RuntimeVersion + * Lookup139: sp_version::RuntimeVersion **/ SpVersionRuntimeVersion: { specName: 'Text', @@ -1278,13 +1417,13 @@ stateVersion: 'u8' }, /** - * Lookup138: frame_system::pallet::Error + * Lookup144: frame_system::pallet::Error **/ FrameSystemError: { _enum: ['InvalidSpecName', 'SpecVersionNeedsToIncrease', 'FailedToExtractRuntimeVersion', 'NonDefaultComposite', 'NonZeroRefCount', 'CallFiltered'] }, /** - * Lookup139: polkadot_primitives::v2::PersistedValidationData + * Lookup145: polkadot_primitives::v2::PersistedValidationData **/ PolkadotPrimitivesV2PersistedValidationData: { parentHead: 'Bytes', @@ -1293,19 +1432,19 @@ maxPovSize: 'u32' }, /** - * Lookup142: polkadot_primitives::v2::UpgradeRestriction + * Lookup148: polkadot_primitives::v2::UpgradeRestriction **/ PolkadotPrimitivesV2UpgradeRestriction: { _enum: ['Present'] }, /** - * Lookup143: sp_trie::storage_proof::StorageProof + * Lookup149: sp_trie::storage_proof::StorageProof **/ SpTrieStorageProof: { trieNodes: 'BTreeSet' }, /** - * Lookup145: cumulus_pallet_parachain_system::relay_state_snapshot::MessagingStateSnapshot + * Lookup151: cumulus_pallet_parachain_system::relay_state_snapshot::MessagingStateSnapshot **/ CumulusPalletParachainSystemRelayStateSnapshotMessagingStateSnapshot: { dmqMqcHead: 'H256', @@ -1314,7 +1453,7 @@ egressChannels: 'Vec<(u32,PolkadotPrimitivesV2AbridgedHrmpChannel)>' }, /** - * Lookup148: polkadot_primitives::v2::AbridgedHrmpChannel + * Lookup154: polkadot_primitives::v2::AbridgedHrmpChannel **/ PolkadotPrimitivesV2AbridgedHrmpChannel: { maxCapacity: 'u32', @@ -1325,7 +1464,7 @@ mqcHead: 'Option' }, /** - * Lookup149: polkadot_primitives::v2::AbridgedHostConfiguration + * Lookup155: polkadot_primitives::v2::AbridgedHostConfiguration **/ PolkadotPrimitivesV2AbridgedHostConfiguration: { maxCodeSize: 'u32', @@ -1339,14 +1478,14 @@ validationUpgradeDelay: 'u32' }, /** - * Lookup155: polkadot_core_primitives::OutboundHrmpMessage + * Lookup161: polkadot_core_primitives::OutboundHrmpMessage **/ PolkadotCorePrimitivesOutboundHrmpMessage: { recipient: 'u32', data: 'Bytes' }, /** - * Lookup156: cumulus_pallet_parachain_system::pallet::Call + * Lookup162: cumulus_pallet_parachain_system::pallet::Call **/ CumulusPalletParachainSystemCall: { _enum: { @@ -1365,7 +1504,7 @@ } }, /** - * Lookup157: cumulus_primitives_parachain_inherent::ParachainInherentData + * Lookup163: cumulus_primitives_parachain_inherent::ParachainInherentData **/ CumulusPrimitivesParachainInherentParachainInherentData: { validationData: 'PolkadotPrimitivesV2PersistedValidationData', @@ -1374,27 +1513,27 @@ horizontalMessages: 'BTreeMap>' }, /** - * Lookup159: polkadot_core_primitives::InboundDownwardMessage + * Lookup165: polkadot_core_primitives::InboundDownwardMessage **/ PolkadotCorePrimitivesInboundDownwardMessage: { sentAt: 'u32', msg: 'Bytes' }, /** - * Lookup162: polkadot_core_primitives::InboundHrmpMessage + * Lookup168: polkadot_core_primitives::InboundHrmpMessage **/ PolkadotCorePrimitivesInboundHrmpMessage: { sentAt: 'u32', data: 'Bytes' }, /** - * Lookup165: cumulus_pallet_parachain_system::pallet::Error + * Lookup171: cumulus_pallet_parachain_system::pallet::Error **/ CumulusPalletParachainSystemError: { _enum: ['OverlappingUpgrades', 'ProhibitedByPolkadot', 'TooBig', 'ValidationDataNotAvailable', 'HostConfigurationNotAvailable', 'NotScheduled', 'NothingAuthorized', 'Unauthorized'] }, /** - * Lookup167: pallet_balances::BalanceLock + * Lookup173: pallet_balances::BalanceLock **/ PalletBalancesBalanceLock: { id: '[u8;8]', @@ -1402,26 +1541,26 @@ reasons: 'PalletBalancesReasons' }, /** - * Lookup168: pallet_balances::Reasons + * Lookup174: pallet_balances::Reasons **/ PalletBalancesReasons: { _enum: ['Fee', 'Misc', 'All'] }, /** - * Lookup171: pallet_balances::ReserveData + * Lookup177: pallet_balances::ReserveData **/ PalletBalancesReserveData: { id: '[u8;16]', amount: 'u128' }, /** - * Lookup173: pallet_balances::Releases + * Lookup179: pallet_balances::Releases **/ PalletBalancesReleases: { _enum: ['V1_0_0', 'V2_0_0'] }, /** - * Lookup174: pallet_balances::pallet::Call + * Lookup180: pallet_balances::pallet::Call **/ PalletBalancesCall: { _enum: { @@ -1454,13 +1593,13 @@ } }, /** - * Lookup177: pallet_balances::pallet::Error + * Lookup183: pallet_balances::pallet::Error **/ PalletBalancesError: { _enum: ['VestingBalance', 'LiquidityRestrictions', 'InsufficientBalance', 'ExistentialDeposit', 'KeepAlive', 'ExistingVestingSchedule', 'DeadAccount', 'TooManyReserves'] }, /** - * Lookup179: pallet_timestamp::pallet::Call + * Lookup185: pallet_timestamp::pallet::Call **/ PalletTimestampCall: { _enum: { @@ -1470,13 +1609,13 @@ } }, /** - * Lookup181: pallet_transaction_payment::Releases + * Lookup187: pallet_transaction_payment::Releases **/ PalletTransactionPaymentReleases: { _enum: ['V1Ancient', 'V2'] }, /** - * Lookup182: pallet_treasury::Proposal + * Lookup188: pallet_treasury::Proposal **/ PalletTreasuryProposal: { proposer: 'AccountId32', @@ -1485,7 +1624,7 @@ bond: 'u128' }, /** - * Lookup185: pallet_treasury::pallet::Call + * Lookup191: pallet_treasury::pallet::Call **/ PalletTreasuryCall: { _enum: { @@ -1509,17 +1648,17 @@ } }, /** - * Lookup188: frame_support::PalletId + * Lookup194: frame_support::PalletId **/ FrameSupportPalletId: '[u8;8]', /** - * Lookup189: pallet_treasury::pallet::Error + * Lookup195: pallet_treasury::pallet::Error **/ PalletTreasuryError: { _enum: ['InsufficientProposersBalance', 'InvalidIndex', 'TooManyApprovals', 'InsufficientPermission', 'ProposalNotApproved'] }, /** - * Lookup190: pallet_sudo::pallet::Call + * Lookup196: pallet_sudo::pallet::Call **/ PalletSudoCall: { _enum: { @@ -1543,7 +1682,7 @@ } }, /** - * Lookup192: orml_vesting::module::Call + * Lookup198: orml_vesting::module::Call **/ OrmlVestingModuleCall: { _enum: { @@ -1562,8 +1701,94 @@ } }, /** - * Lookup194: cumulus_pallet_xcmp_queue::pallet::Call + * Lookup200: orml_xtokens::module::Call **/ + OrmlXtokensModuleCall: { + _enum: { + transfer: { + currencyId: 'PalletForeignAssetsAssetIds', + amount: 'u128', + dest: 'XcmVersionedMultiLocation', + destWeight: 'u64', + }, + transfer_multiasset: { + asset: 'XcmVersionedMultiAsset', + dest: 'XcmVersionedMultiLocation', + destWeight: 'u64', + }, + transfer_with_fee: { + currencyId: 'PalletForeignAssetsAssetIds', + amount: 'u128', + fee: 'u128', + dest: 'XcmVersionedMultiLocation', + destWeight: 'u64', + }, + transfer_multiasset_with_fee: { + asset: 'XcmVersionedMultiAsset', + fee: 'XcmVersionedMultiAsset', + dest: 'XcmVersionedMultiLocation', + destWeight: 'u64', + }, + transfer_multicurrencies: { + currencies: 'Vec<(PalletForeignAssetsAssetIds,u128)>', + feeItem: 'u32', + dest: 'XcmVersionedMultiLocation', + destWeight: 'u64', + }, + transfer_multiassets: { + assets: 'XcmVersionedMultiAssets', + feeItem: 'u32', + dest: 'XcmVersionedMultiLocation', + destWeight: 'u64' + } + } + }, + /** + * Lookup201: xcm::VersionedMultiAsset + **/ + XcmVersionedMultiAsset: { + _enum: { + V0: 'XcmV0MultiAsset', + V1: 'XcmV1MultiAsset' + } + }, + /** + * Lookup204: orml_tokens::module::Call + **/ + OrmlTokensModuleCall: { + _enum: { + transfer: { + dest: 'MultiAddress', + currencyId: 'PalletForeignAssetsAssetIds', + amount: 'Compact', + }, + transfer_all: { + dest: 'MultiAddress', + currencyId: 'PalletForeignAssetsAssetIds', + keepAlive: 'bool', + }, + transfer_keep_alive: { + dest: 'MultiAddress', + currencyId: 'PalletForeignAssetsAssetIds', + amount: 'Compact', + }, + force_transfer: { + source: 'MultiAddress', + dest: 'MultiAddress', + currencyId: 'PalletForeignAssetsAssetIds', + amount: 'Compact', + }, + set_balance: { + who: 'MultiAddress', + currencyId: 'PalletForeignAssetsAssetIds', + newFree: 'Compact', + newReserved: 'Compact' + } + } + }, + /** + * Lookup205: cumulus_pallet_xcmp_queue::pallet::Call + **/ CumulusPalletXcmpQueueCall: { _enum: { service_overweight: { @@ -1611,7 +1836,7 @@ } }, /** - * Lookup195: pallet_xcm::pallet::Call + * Lookup206: pallet_xcm::pallet::Call **/ PalletXcmCall: { _enum: { @@ -1665,7 +1890,7 @@ } }, /** - * Lookup196: xcm::VersionedXcm + * Lookup207: xcm::VersionedXcm **/ XcmVersionedXcm: { _enum: { @@ -1675,7 +1900,7 @@ } }, /** - * Lookup197: xcm::v0::Xcm + * Lookup208: xcm::v0::Xcm **/ XcmV0Xcm: { _enum: { @@ -1729,7 +1954,7 @@ } }, /** - * Lookup199: xcm::v0::order::Order + * Lookup210: xcm::v0::order::Order **/ XcmV0Order: { _enum: { @@ -1772,7 +1997,7 @@ } }, /** - * Lookup201: xcm::v0::Response + * Lookup212: xcm::v0::Response **/ XcmV0Response: { _enum: { @@ -1780,7 +2005,7 @@ } }, /** - * Lookup202: xcm::v1::Xcm + * Lookup213: xcm::v1::Xcm **/ XcmV1Xcm: { _enum: { @@ -1839,7 +2064,7 @@ } }, /** - * Lookup204: xcm::v1::order::Order + * Lookup215: xcm::v1::order::Order **/ XcmV1Order: { _enum: { @@ -1884,7 +2109,7 @@ } }, /** - * Lookup206: xcm::v1::Response + * Lookup217: xcm::v1::Response **/ XcmV1Response: { _enum: { @@ -1893,11 +2118,11 @@ } }, /** - * Lookup220: cumulus_pallet_xcm::pallet::Call + * Lookup231: cumulus_pallet_xcm::pallet::Call **/ CumulusPalletXcmCall: 'Null', /** - * Lookup221: cumulus_pallet_dmp_queue::pallet::Call + * Lookup232: cumulus_pallet_dmp_queue::pallet::Call **/ CumulusPalletDmpQueueCall: { _enum: { @@ -1908,7 +2133,7 @@ } }, /** - * Lookup222: pallet_inflation::pallet::Call + * Lookup233: pallet_inflation::pallet::Call **/ PalletInflationCall: { _enum: { @@ -1918,7 +2143,7 @@ } }, /** - * Lookup223: pallet_unique::Call + * Lookup234: pallet_unique::Call **/ PalletUniqueCall: { _enum: { @@ -2050,7 +2275,7 @@ } }, /** - * Lookup228: up_data_structs::CollectionMode + * Lookup239: up_data_structs::CollectionMode **/ UpDataStructsCollectionMode: { _enum: { @@ -2060,7 +2285,7 @@ } }, /** - * Lookup229: up_data_structs::CreateCollectionData + * Lookup240: up_data_structs::CreateCollectionData **/ UpDataStructsCreateCollectionData: { mode: 'UpDataStructsCollectionMode', @@ -2075,13 +2300,13 @@ properties: 'Vec' }, /** - * Lookup231: up_data_structs::AccessMode + * Lookup242: up_data_structs::AccessMode **/ UpDataStructsAccessMode: { _enum: ['Normal', 'AllowList'] }, /** - * Lookup233: up_data_structs::CollectionLimits + * Lookup244: up_data_structs::CollectionLimits **/ UpDataStructsCollectionLimits: { accountTokenOwnershipLimit: 'Option', @@ -2095,7 +2320,7 @@ transfersEnabled: 'Option' }, /** - * Lookup235: up_data_structs::SponsoringRateLimit + * Lookup246: up_data_structs::SponsoringRateLimit **/ UpDataStructsSponsoringRateLimit: { _enum: { @@ -2104,7 +2329,7 @@ } }, /** - * Lookup238: up_data_structs::CollectionPermissions + * Lookup249: up_data_structs::CollectionPermissions **/ UpDataStructsCollectionPermissions: { access: 'Option', @@ -2112,7 +2337,7 @@ nesting: 'Option' }, /** - * Lookup240: up_data_structs::NestingPermissions + * Lookup251: up_data_structs::NestingPermissions **/ UpDataStructsNestingPermissions: { tokenOwner: 'bool', @@ -2120,18 +2345,18 @@ restricted: 'Option' }, /** - * Lookup242: up_data_structs::OwnerRestrictedSet + * Lookup253: up_data_structs::OwnerRestrictedSet **/ UpDataStructsOwnerRestrictedSet: 'BTreeSet', /** - * Lookup247: up_data_structs::PropertyKeyPermission + * Lookup258: up_data_structs::PropertyKeyPermission **/ UpDataStructsPropertyKeyPermission: { key: 'Bytes', permission: 'UpDataStructsPropertyPermission' }, /** - * Lookup248: up_data_structs::PropertyPermission + * Lookup259: up_data_structs::PropertyPermission **/ UpDataStructsPropertyPermission: { mutable: 'bool', @@ -2139,14 +2364,14 @@ tokenOwner: 'bool' }, /** - * Lookup251: up_data_structs::Property + * Lookup262: up_data_structs::Property **/ UpDataStructsProperty: { key: 'Bytes', value: 'Bytes' }, /** - * Lookup254: up_data_structs::CreateItemData + * Lookup265: up_data_structs::CreateItemData **/ UpDataStructsCreateItemData: { _enum: { @@ -2156,26 +2381,26 @@ } }, /** - * Lookup255: up_data_structs::CreateNftData + * Lookup266: up_data_structs::CreateNftData **/ UpDataStructsCreateNftData: { properties: 'Vec' }, /** - * Lookup256: up_data_structs::CreateFungibleData + * Lookup267: up_data_structs::CreateFungibleData **/ UpDataStructsCreateFungibleData: { value: 'u128' }, /** - * Lookup257: up_data_structs::CreateReFungibleData + * Lookup268: up_data_structs::CreateReFungibleData **/ UpDataStructsCreateReFungibleData: { pieces: 'u128', properties: 'Vec' }, /** - * Lookup260: up_data_structs::CreateItemExData> + * Lookup271: up_data_structs::CreateItemExData> **/ UpDataStructsCreateItemExData: { _enum: { @@ -2186,14 +2411,14 @@ } }, /** - * Lookup262: up_data_structs::CreateNftExData> + * Lookup273: up_data_structs::CreateNftExData> **/ UpDataStructsCreateNftExData: { properties: 'Vec', owner: 'PalletEvmAccountBasicCrossAccountIdRepr' }, /** - * Lookup269: up_data_structs::CreateRefungibleExSingleOwner> + * Lookup280: up_data_structs::CreateRefungibleExSingleOwner> **/ UpDataStructsCreateRefungibleExSingleOwner: { user: 'PalletEvmAccountBasicCrossAccountIdRepr', @@ -2201,14 +2426,14 @@ properties: 'Vec' }, /** - * Lookup271: up_data_structs::CreateRefungibleExMultipleOwners> + * Lookup282: up_data_structs::CreateRefungibleExMultipleOwners> **/ UpDataStructsCreateRefungibleExMultipleOwners: { users: 'BTreeMap', properties: 'Vec' }, /** - * Lookup272: pallet_unique_scheduler::pallet::Call + * Lookup283: pallet_unique_scheduler::pallet::Call **/ PalletUniqueSchedulerCall: { _enum: { @@ -2232,7 +2457,7 @@ } }, /** - * Lookup274: frame_support::traits::schedule::MaybeHashed + * Lookup285: frame_support::traits::schedule::MaybeHashed **/ FrameSupportScheduleMaybeHashed: { _enum: { @@ -2241,7 +2466,7 @@ } }, /** - * Lookup275: pallet_configuration::pallet::Call + * Lookup286: pallet_configuration::pallet::Call **/ PalletConfigurationCall: { _enum: { @@ -2254,15 +2479,15 @@ } }, /** - * Lookup276: pallet_template_transaction_payment::Call + * Lookup287: pallet_template_transaction_payment::Call **/ PalletTemplateTransactionPaymentCall: 'Null', /** - * Lookup277: pallet_structure::pallet::Call + * Lookup288: pallet_structure::pallet::Call **/ PalletStructureCall: 'Null', /** - * Lookup278: pallet_rmrk_core::pallet::Call + * Lookup289: pallet_rmrk_core::pallet::Call **/ PalletRmrkCoreCall: { _enum: { @@ -2353,7 +2578,7 @@ } }, /** - * Lookup284: rmrk_traits::resource::ResourceTypes, sp_runtime::bounded::bounded_vec::BoundedVec> + * Lookup295: rmrk_traits::resource::ResourceTypes, sp_runtime::bounded::bounded_vec::BoundedVec> **/ RmrkTraitsResourceResourceTypes: { _enum: { @@ -2363,7 +2588,7 @@ } }, /** - * Lookup286: rmrk_traits::resource::BasicResource> + * Lookup297: rmrk_traits::resource::BasicResource> **/ RmrkTraitsResourceBasicResource: { src: 'Option', @@ -2372,7 +2597,7 @@ thumb: 'Option' }, /** - * Lookup288: rmrk_traits::resource::ComposableResource, sp_runtime::bounded::bounded_vec::BoundedVec> + * Lookup299: rmrk_traits::resource::ComposableResource, sp_runtime::bounded::bounded_vec::BoundedVec> **/ RmrkTraitsResourceComposableResource: { parts: 'Vec', @@ -2383,7 +2608,7 @@ thumb: 'Option' }, /** - * Lookup289: rmrk_traits::resource::SlotResource> + * Lookup300: rmrk_traits::resource::SlotResource> **/ RmrkTraitsResourceSlotResource: { base: 'u32', @@ -2394,7 +2619,7 @@ thumb: 'Option' }, /** - * Lookup292: pallet_rmrk_equip::pallet::Call + * Lookup303: pallet_rmrk_equip::pallet::Call **/ PalletRmrkEquipCall: { _enum: { @@ -2415,7 +2640,7 @@ } }, /** - * Lookup295: rmrk_traits::part::PartType, sp_runtime::bounded::bounded_vec::BoundedVec> + * Lookup306: rmrk_traits::part::PartType, sp_runtime::bounded::bounded_vec::BoundedVec> **/ RmrkTraitsPartPartType: { _enum: { @@ -2424,7 +2649,7 @@ } }, /** - * Lookup297: rmrk_traits::part::FixedPart> + * Lookup308: rmrk_traits::part::FixedPart> **/ RmrkTraitsPartFixedPart: { id: 'u32', @@ -2432,7 +2657,7 @@ src: 'Bytes' }, /** - * Lookup298: rmrk_traits::part::SlotPart, sp_runtime::bounded::bounded_vec::BoundedVec> + * Lookup309: rmrk_traits::part::SlotPart, sp_runtime::bounded::bounded_vec::BoundedVec> **/ RmrkTraitsPartSlotPart: { id: 'u32', @@ -2441,7 +2666,7 @@ z: 'u32' }, /** - * Lookup299: rmrk_traits::part::EquippableList> + * Lookup310: rmrk_traits::part::EquippableList> **/ RmrkTraitsPartEquippableList: { _enum: { @@ -2451,7 +2676,7 @@ } }, /** - * Lookup301: rmrk_traits::theme::Theme, sp_runtime::bounded::bounded_vec::BoundedVec>, S>> + * Lookup312: rmrk_traits::theme::Theme, sp_runtime::bounded::bounded_vec::BoundedVec>, S>> **/ RmrkTraitsTheme: { name: 'Bytes', @@ -2459,14 +2684,14 @@ inherit: 'bool' }, /** - * Lookup303: rmrk_traits::theme::ThemeProperty> + * Lookup314: rmrk_traits::theme::ThemeProperty> **/ RmrkTraitsThemeThemeProperty: { key: 'Bytes', value: 'Bytes' }, /** - * Lookup305: pallet_app_promotion::pallet::Call + * Lookup316: pallet_app_promotion::pallet::Call **/ PalletAppPromotionCall: { _enum: { @@ -2495,8 +2720,25 @@ } }, /** - * Lookup307: pallet_evm::pallet::Call + * Lookup318: pallet_foreign_assets::module::Call **/ + PalletForeignAssetsModuleCall: { + _enum: { + register_foreign_asset: { + owner: 'AccountId32', + location: 'XcmVersionedMultiLocation', + metadata: 'PalletForeignAssetsModuleAssetMetadata', + }, + update_foreign_asset: { + foreignAssetId: 'u32', + location: 'XcmVersionedMultiLocation', + metadata: 'PalletForeignAssetsModuleAssetMetadata' + } + } + }, + /** + * Lookup319: pallet_evm::pallet::Call + **/ PalletEvmCall: { _enum: { withdraw: { @@ -2538,7 +2780,7 @@ } }, /** - * Lookup311: pallet_ethereum::pallet::Call + * Lookup323: pallet_ethereum::pallet::Call **/ PalletEthereumCall: { _enum: { @@ -2548,7 +2790,7 @@ } }, /** - * Lookup312: ethereum::transaction::TransactionV2 + * Lookup324: ethereum::transaction::TransactionV2 **/ EthereumTransactionTransactionV2: { _enum: { @@ -2558,7 +2800,7 @@ } }, /** - * Lookup313: ethereum::transaction::LegacyTransaction + * Lookup325: ethereum::transaction::LegacyTransaction **/ EthereumTransactionLegacyTransaction: { nonce: 'U256', @@ -2570,7 +2812,7 @@ signature: 'EthereumTransactionTransactionSignature' }, /** - * Lookup314: ethereum::transaction::TransactionAction + * Lookup326: ethereum::transaction::TransactionAction **/ EthereumTransactionTransactionAction: { _enum: { @@ -2579,7 +2821,7 @@ } }, /** - * Lookup315: ethereum::transaction::TransactionSignature + * Lookup327: ethereum::transaction::TransactionSignature **/ EthereumTransactionTransactionSignature: { v: 'u64', @@ -2587,7 +2829,7 @@ s: 'H256' }, /** - * Lookup317: ethereum::transaction::EIP2930Transaction + * Lookup329: ethereum::transaction::EIP2930Transaction **/ EthereumTransactionEip2930Transaction: { chainId: 'u64', @@ -2603,14 +2845,14 @@ s: 'H256' }, /** - * Lookup319: ethereum::transaction::AccessListItem + * Lookup331: ethereum::transaction::AccessListItem **/ EthereumTransactionAccessListItem: { address: 'H160', storageKeys: 'Vec' }, /** - * Lookup320: ethereum::transaction::EIP1559Transaction + * Lookup332: ethereum::transaction::EIP1559Transaction **/ EthereumTransactionEip1559Transaction: { chainId: 'u64', @@ -2627,7 +2869,7 @@ s: 'H256' }, /** - * Lookup321: pallet_evm_migration::pallet::Call + * Lookup333: pallet_evm_migration::pallet::Call **/ PalletEvmMigrationCall: { _enum: { @@ -2645,39 +2887,73 @@ } }, /** - * Lookup324: pallet_sudo::pallet::Error + * Lookup336: pallet_sudo::pallet::Error **/ PalletSudoError: { _enum: ['RequireSudo'] }, /** - * Lookup326: orml_vesting::module::Error + * Lookup338: orml_vesting::module::Error **/ OrmlVestingModuleError: { _enum: ['ZeroVestingPeriod', 'ZeroVestingPeriodCount', 'InsufficientBalanceToLock', 'TooManyVestingSchedules', 'AmountLow', 'MaxVestingSchedulesExceeded'] }, /** - * Lookup328: cumulus_pallet_xcmp_queue::InboundChannelDetails + * Lookup339: orml_xtokens::module::Error + **/ + OrmlXtokensModuleError: { + _enum: ['AssetHasNoReserve', 'NotCrossChainTransfer', 'InvalidDest', 'NotCrossChainTransferableCurrency', 'UnweighableMessage', 'XcmExecutionFailed', 'CannotReanchor', 'InvalidAncestry', 'InvalidAsset', 'DestinationNotInvertible', 'BadVersion', 'DistinctReserveForAssetAndFee', 'ZeroFee', 'ZeroAmount', 'TooManyAssetsBeingSent', 'AssetIndexNonExistent', 'FeeNotEnough', 'NotSupportedMultiLocation', 'MinXcmFeeNotDefined'] + }, + /** + * Lookup342: orml_tokens::BalanceLock + **/ + OrmlTokensBalanceLock: { + id: '[u8;8]', + amount: 'u128' + }, + /** + * Lookup344: orml_tokens::AccountData + **/ + OrmlTokensAccountData: { + free: 'u128', + reserved: 'u128', + frozen: 'u128' + }, + /** + * Lookup346: orml_tokens::ReserveData **/ + OrmlTokensReserveData: { + id: 'Null', + amount: 'u128' + }, + /** + * Lookup348: orml_tokens::module::Error + **/ + OrmlTokensModuleError: { + _enum: ['BalanceTooLow', 'AmountIntoBalanceFailed', 'LiquidityRestrictions', 'MaxLocksExceeded', 'KeepAlive', 'ExistentialDeposit', 'DeadAccount', 'TooManyReserves'] + }, + /** + * Lookup350: cumulus_pallet_xcmp_queue::InboundChannelDetails + **/ CumulusPalletXcmpQueueInboundChannelDetails: { sender: 'u32', state: 'CumulusPalletXcmpQueueInboundState', messageMetadata: 'Vec<(u32,PolkadotParachainPrimitivesXcmpMessageFormat)>' }, /** - * Lookup329: cumulus_pallet_xcmp_queue::InboundState + * Lookup351: cumulus_pallet_xcmp_queue::InboundState **/ CumulusPalletXcmpQueueInboundState: { _enum: ['Ok', 'Suspended'] }, /** - * Lookup332: polkadot_parachain::primitives::XcmpMessageFormat + * Lookup354: polkadot_parachain::primitives::XcmpMessageFormat **/ PolkadotParachainPrimitivesXcmpMessageFormat: { _enum: ['ConcatenatedVersionedXcm', 'ConcatenatedEncodedBlob', 'Signals'] }, /** - * Lookup335: cumulus_pallet_xcmp_queue::OutboundChannelDetails + * Lookup357: cumulus_pallet_xcmp_queue::OutboundChannelDetails **/ CumulusPalletXcmpQueueOutboundChannelDetails: { recipient: 'u32', @@ -2687,13 +2963,13 @@ lastIndex: 'u16' }, /** - * Lookup336: cumulus_pallet_xcmp_queue::OutboundState + * Lookup358: cumulus_pallet_xcmp_queue::OutboundState **/ CumulusPalletXcmpQueueOutboundState: { _enum: ['Ok', 'Suspended'] }, /** - * Lookup338: cumulus_pallet_xcmp_queue::QueueConfigData + * Lookup360: cumulus_pallet_xcmp_queue::QueueConfigData **/ CumulusPalletXcmpQueueQueueConfigData: { suspendThreshold: 'u32', @@ -2704,29 +2980,29 @@ xcmpMaxIndividualWeight: 'u64' }, /** - * Lookup340: cumulus_pallet_xcmp_queue::pallet::Error + * Lookup362: cumulus_pallet_xcmp_queue::pallet::Error **/ CumulusPalletXcmpQueueError: { _enum: ['FailedToSend', 'BadXcmOrigin', 'BadXcm', 'BadOverweightIndex', 'WeightOverLimit'] }, /** - * Lookup341: pallet_xcm::pallet::Error + * Lookup363: pallet_xcm::pallet::Error **/ PalletXcmError: { _enum: ['Unreachable', 'SendFailure', 'Filtered', 'UnweighableMessage', 'DestinationNotInvertible', 'Empty', 'CannotReanchor', 'TooManyAssets', 'InvalidOrigin', 'BadVersion', 'BadLocation', 'NoSubscription', 'AlreadySubscribed'] }, /** - * Lookup342: cumulus_pallet_xcm::pallet::Error + * Lookup364: cumulus_pallet_xcm::pallet::Error **/ CumulusPalletXcmError: 'Null', /** - * Lookup343: cumulus_pallet_dmp_queue::ConfigData + * Lookup365: cumulus_pallet_dmp_queue::ConfigData **/ CumulusPalletDmpQueueConfigData: { maxIndividual: 'u64' }, /** - * Lookup344: cumulus_pallet_dmp_queue::PageIndexData + * Lookup366: cumulus_pallet_dmp_queue::PageIndexData **/ CumulusPalletDmpQueuePageIndexData: { beginUsed: 'u32', @@ -2734,19 +3010,19 @@ overweightCount: 'u64' }, /** - * Lookup347: cumulus_pallet_dmp_queue::pallet::Error + * Lookup369: cumulus_pallet_dmp_queue::pallet::Error **/ CumulusPalletDmpQueueError: { _enum: ['Unknown', 'OverLimit'] }, /** - * Lookup351: pallet_unique::Error + * Lookup373: pallet_unique::Error **/ PalletUniqueError: { _enum: ['CollectionDecimalPointLimitExceeded', 'ConfirmUnsetSponsorFail', 'EmptyArgument', 'RepartitionCalledOnNonRefungibleCollection'] }, /** - * Lookup354: pallet_unique_scheduler::ScheduledV3, BlockNumber, opal_runtime::OriginCaller, sp_core::crypto::AccountId32> + * Lookup376: pallet_unique_scheduler::ScheduledV3, BlockNumber, opal_runtime::OriginCaller, sp_core::crypto::AccountId32> **/ PalletUniqueSchedulerScheduledV3: { maybeId: 'Option<[u8;16]>', @@ -2756,7 +3032,7 @@ origin: 'OpalRuntimeOriginCaller' }, /** - * Lookup355: opal_runtime::OriginCaller + * Lookup377: opal_runtime::OriginCaller **/ OpalRuntimeOriginCaller: { _enum: { @@ -2865,7 +3141,7 @@ } }, /** - * Lookup356: frame_support::dispatch::RawOrigin + * Lookup378: frame_support::dispatch::RawOrigin **/ FrameSupportDispatchRawOrigin: { _enum: { @@ -2875,7 +3151,7 @@ } }, /** - * Lookup357: pallet_xcm::pallet::Origin + * Lookup379: pallet_xcm::pallet::Origin **/ PalletXcmOrigin: { _enum: { @@ -2884,7 +3160,7 @@ } }, /** - * Lookup358: cumulus_pallet_xcm::pallet::Origin + * Lookup380: cumulus_pallet_xcm::pallet::Origin **/ CumulusPalletXcmOrigin: { _enum: { @@ -2893,7 +3169,7 @@ } }, /** - * Lookup359: pallet_ethereum::RawOrigin + * Lookup381: pallet_ethereum::RawOrigin **/ PalletEthereumRawOrigin: { _enum: { @@ -2901,17 +3177,17 @@ } }, /** - * Lookup360: sp_core::Void + * Lookup382: sp_core::Void **/ SpCoreVoid: 'Null', /** - * Lookup361: pallet_unique_scheduler::pallet::Error + * Lookup383: pallet_unique_scheduler::pallet::Error **/ PalletUniqueSchedulerError: { _enum: ['FailedToSchedule', 'NotFound', 'TargetBlockNumberInPast', 'RescheduleNoChange'] }, /** - * Lookup362: up_data_structs::Collection + * Lookup384: up_data_structs::Collection **/ UpDataStructsCollection: { owner: 'AccountId32', @@ -2922,10 +3198,10 @@ sponsorship: 'UpDataStructsSponsorshipStateAccountId32', limits: 'UpDataStructsCollectionLimits', permissions: 'UpDataStructsCollectionPermissions', - externalCollection: 'bool' + flags: '[u8;1]' }, /** - * Lookup363: up_data_structs::SponsorshipState + * Lookup385: up_data_structs::SponsorshipState **/ UpDataStructsSponsorshipStateAccountId32: { _enum: { @@ -2935,7 +3211,7 @@ } }, /** - * Lookup364: up_data_structs::Properties + * Lookup387: up_data_structs::Properties **/ UpDataStructsProperties: { map: 'UpDataStructsPropertiesMapBoundedVec', @@ -2943,15 +3219,15 @@ spaceLimit: 'u32' }, /** - * Lookup365: up_data_structs::PropertiesMap> + * Lookup388: up_data_structs::PropertiesMap> **/ UpDataStructsPropertiesMapBoundedVec: 'BTreeMap', /** - * Lookup370: up_data_structs::PropertiesMap + * Lookup393: up_data_structs::PropertiesMap **/ UpDataStructsPropertiesMapPropertyPermission: 'BTreeMap', /** - * Lookup377: up_data_structs::CollectionStats + * Lookup400: up_data_structs::CollectionStats **/ UpDataStructsCollectionStats: { created: 'u32', @@ -2959,18 +3235,18 @@ alive: 'u32' }, /** - * Lookup378: up_data_structs::TokenChild + * Lookup401: up_data_structs::TokenChild **/ UpDataStructsTokenChild: { token: 'u32', collection: 'u32' }, /** - * Lookup379: PhantomType::up_data_structs + * Lookup402: PhantomType::up_data_structs **/ PhantomTypeUpDataStructs: '[(UpDataStructsTokenData,UpDataStructsRpcCollection,RmrkTraitsCollectionCollectionInfo,RmrkTraitsNftNftInfo,RmrkTraitsResourceResourceInfo,RmrkTraitsPropertyPropertyInfo,RmrkTraitsBaseBaseInfo,RmrkTraitsPartPartType,RmrkTraitsTheme,RmrkTraitsNftNftChild);0]', /** - * Lookup381: up_data_structs::TokenData> + * Lookup404: up_data_structs::TokenData> **/ UpDataStructsTokenData: { properties: 'Vec', @@ -2978,7 +3254,7 @@ pieces: 'u128' }, /** - * Lookup383: up_data_structs::RpcCollection + * Lookup406: up_data_structs::RpcCollection **/ UpDataStructsRpcCollection: { owner: 'AccountId32', @@ -2991,10 +3267,11 @@ permissions: 'UpDataStructsCollectionPermissions', tokenPropertyPermissions: 'Vec', properties: 'Vec', - readOnly: 'bool' + readOnly: 'bool', + foreign: 'bool' }, /** - * Lookup384: rmrk_traits::collection::CollectionInfo, sp_runtime::bounded::bounded_vec::BoundedVec, sp_core::crypto::AccountId32> + * Lookup407: rmrk_traits::collection::CollectionInfo, sp_runtime::bounded::bounded_vec::BoundedVec, sp_core::crypto::AccountId32> **/ RmrkTraitsCollectionCollectionInfo: { issuer: 'AccountId32', @@ -3004,7 +3281,7 @@ nftsCount: 'u32' }, /** - * Lookup385: rmrk_traits::nft::NftInfo> + * Lookup408: rmrk_traits::nft::NftInfo> **/ RmrkTraitsNftNftInfo: { owner: 'RmrkTraitsNftAccountIdOrCollectionNftTuple', @@ -3014,14 +3291,14 @@ pending: 'bool' }, /** - * Lookup387: rmrk_traits::nft::RoyaltyInfo + * Lookup410: rmrk_traits::nft::RoyaltyInfo **/ RmrkTraitsNftRoyaltyInfo: { recipient: 'AccountId32', amount: 'Permill' }, /** - * Lookup388: rmrk_traits::resource::ResourceInfo, sp_runtime::bounded::bounded_vec::BoundedVec> + * Lookup411: rmrk_traits::resource::ResourceInfo, sp_runtime::bounded::bounded_vec::BoundedVec> **/ RmrkTraitsResourceResourceInfo: { id: 'u32', @@ -3030,14 +3307,14 @@ pendingRemoval: 'bool' }, /** - * Lookup389: rmrk_traits::property::PropertyInfo, sp_runtime::bounded::bounded_vec::BoundedVec> + * Lookup412: rmrk_traits::property::PropertyInfo, sp_runtime::bounded::bounded_vec::BoundedVec> **/ RmrkTraitsPropertyPropertyInfo: { key: 'Bytes', value: 'Bytes' }, /** - * Lookup390: rmrk_traits::base::BaseInfo> + * Lookup413: rmrk_traits::base::BaseInfo> **/ RmrkTraitsBaseBaseInfo: { issuer: 'AccountId32', @@ -3045,86 +3322,92 @@ symbol: 'Bytes' }, /** - * Lookup391: rmrk_traits::nft::NftChild + * Lookup414: rmrk_traits::nft::NftChild **/ RmrkTraitsNftNftChild: { collectionId: 'u32', nftId: 'u32' }, /** - * Lookup393: pallet_common::pallet::Error + * Lookup416: pallet_common::pallet::Error **/ PalletCommonError: { _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'] }, /** - * Lookup395: pallet_fungible::pallet::Error + * Lookup418: pallet_fungible::pallet::Error **/ PalletFungibleError: { _enum: ['NotFungibleDataUsedToMintFungibleCollectionToken', 'FungibleItemsHaveNoId', 'FungibleItemsDontHaveData', 'FungibleDisallowsNesting', 'SettingPropertiesNotAllowed'] }, /** - * Lookup396: pallet_refungible::ItemData + * Lookup419: pallet_refungible::ItemData **/ PalletRefungibleItemData: { constData: 'Bytes' }, /** - * Lookup401: pallet_refungible::pallet::Error + * Lookup424: pallet_refungible::pallet::Error **/ PalletRefungibleError: { _enum: ['NotRefungibleDataUsedToMintFungibleCollectionToken', 'WrongRefungiblePieces', 'RepartitionWhileNotOwningAllPieces', 'RefungibleDisallowsNesting', 'SettingPropertiesNotAllowed'] }, /** - * Lookup402: pallet_nonfungible::ItemData> + * Lookup425: pallet_nonfungible::ItemData> **/ PalletNonfungibleItemData: { owner: 'PalletEvmAccountBasicCrossAccountIdRepr' }, /** - * Lookup404: up_data_structs::PropertyScope + * Lookup427: up_data_structs::PropertyScope **/ UpDataStructsPropertyScope: { _enum: ['None', 'Rmrk'] }, /** - * Lookup406: pallet_nonfungible::pallet::Error + * Lookup429: pallet_nonfungible::pallet::Error **/ PalletNonfungibleError: { _enum: ['NotNonfungibleDataUsedToMintFungibleCollectionToken', 'NonfungibleItemsHaveNoAmount', 'CantBurnNftWithChildren'] }, /** - * Lookup407: pallet_structure::pallet::Error + * Lookup430: pallet_structure::pallet::Error **/ PalletStructureError: { _enum: ['OuroborosDetected', 'DepthLimit', 'BreadthLimit', 'TokenNotFound'] }, /** - * Lookup408: pallet_rmrk_core::pallet::Error + * Lookup431: pallet_rmrk_core::pallet::Error **/ PalletRmrkCoreError: { _enum: ['CorruptedCollectionType', 'RmrkPropertyKeyIsTooLong', 'RmrkPropertyValueIsTooLong', 'RmrkPropertyIsNotFound', 'UnableToDecodeRmrkData', 'CollectionNotEmpty', 'NoAvailableCollectionId', 'NoAvailableNftId', 'CollectionUnknown', 'NoPermission', 'NonTransferable', 'CollectionFullOrLocked', 'ResourceDoesntExist', 'CannotSendToDescendentOrSelf', 'CannotAcceptNonOwnedNft', 'CannotRejectNonOwnedNft', 'CannotRejectNonPendingNft', 'ResourceNotPending', 'NoAvailableResourceId'] }, /** - * Lookup410: pallet_rmrk_equip::pallet::Error + * Lookup433: pallet_rmrk_equip::pallet::Error **/ PalletRmrkEquipError: { _enum: ['PermissionError', 'NoAvailableBaseId', 'NoAvailablePartId', 'BaseDoesntExist', 'NeedsDefaultThemeFirst', 'PartDoesntExist', 'NoEquippableOnFixedPart'] }, /** - * Lookup416: pallet_app_promotion::pallet::Error + * Lookup439: pallet_app_promotion::pallet::Error **/ PalletAppPromotionError: { _enum: ['AdminNotSet', 'NoPermission', 'NotSufficientFunds', 'PendingForBlockOverflow', 'SponsorNotSet', 'IncorrectLockedBalanceOperation'] }, /** - * Lookup419: pallet_evm::pallet::Error + * Lookup440: pallet_foreign_assets::module::Error + **/ + PalletForeignAssetsModuleError: { + _enum: ['BadLocation', 'MultiLocationExisted', 'AssetIdNotExists', 'AssetIdExisted'] + }, + /** + * Lookup443: pallet_evm::pallet::Error **/ PalletEvmError: { _enum: ['BalanceLow', 'FeeOverflow', 'PaymentOverflow', 'WithdrawFailed', 'GasPriceTooLow', 'InvalidNonce'] }, /** - * Lookup422: fp_rpc::TransactionStatus + * Lookup446: fp_rpc::TransactionStatus **/ FpRpcTransactionStatus: { transactionHash: 'H256', @@ -3136,11 +3419,11 @@ logsBloom: 'EthbloomBloom' }, /** - * Lookup424: ethbloom::Bloom + * Lookup448: ethbloom::Bloom **/ EthbloomBloom: '[u8;256]', /** - * Lookup426: ethereum::receipt::ReceiptV3 + * Lookup450: ethereum::receipt::ReceiptV3 **/ EthereumReceiptReceiptV3: { _enum: { @@ -3150,7 +3433,7 @@ } }, /** - * Lookup427: ethereum::receipt::EIP658ReceiptData + * Lookup451: ethereum::receipt::EIP658ReceiptData **/ EthereumReceiptEip658ReceiptData: { statusCode: 'u8', @@ -3159,7 +3442,7 @@ logs: 'Vec' }, /** - * Lookup428: ethereum::block::Block + * Lookup452: ethereum::block::Block **/ EthereumBlock: { header: 'EthereumHeader', @@ -3167,7 +3450,7 @@ ommers: 'Vec' }, /** - * Lookup429: ethereum::header::Header + * Lookup453: ethereum::header::Header **/ EthereumHeader: { parentHash: 'H256', @@ -3187,23 +3470,23 @@ nonce: 'EthereumTypesHashH64' }, /** - * Lookup430: ethereum_types::hash::H64 + * Lookup454: ethereum_types::hash::H64 **/ EthereumTypesHashH64: '[u8;8]', /** - * Lookup435: pallet_ethereum::pallet::Error + * Lookup459: pallet_ethereum::pallet::Error **/ PalletEthereumError: { _enum: ['InvalidSignature', 'PreLogExists'] }, /** - * Lookup436: pallet_evm_coder_substrate::pallet::Error + * Lookup460: pallet_evm_coder_substrate::pallet::Error **/ PalletEvmCoderSubstrateError: { _enum: ['OutOfGas', 'OutOfFund'] }, /** - * Lookup437: up_data_structs::SponsorshipState> + * Lookup461: up_data_structs::SponsorshipState> **/ UpDataStructsSponsorshipStateBasicCrossAccountIdRepr: { _enum: { @@ -3213,25 +3496,25 @@ } }, /** - * Lookup438: pallet_evm_contract_helpers::SponsoringModeT + * Lookup462: pallet_evm_contract_helpers::SponsoringModeT **/ PalletEvmContractHelpersSponsoringModeT: { _enum: ['Disabled', 'Allowlisted', 'Generous'] }, /** - * Lookup440: pallet_evm_contract_helpers::pallet::Error + * Lookup468: pallet_evm_contract_helpers::pallet::Error **/ PalletEvmContractHelpersError: { - _enum: ['NoPermission', 'NoPendingSponsor'] + _enum: ['NoPermission', 'NoPendingSponsor', 'TooManyMethodsHaveSponsoredLimit'] }, /** - * Lookup441: pallet_evm_migration::pallet::Error + * Lookup469: pallet_evm_migration::pallet::Error **/ PalletEvmMigrationError: { _enum: ['AccountNotEmpty', 'AccountIsNotMigrating'] }, /** - * Lookup443: sp_runtime::MultiSignature + * Lookup471: sp_runtime::MultiSignature **/ SpRuntimeMultiSignature: { _enum: { @@ -3241,43 +3524,43 @@ } }, /** - * Lookup444: sp_core::ed25519::Signature + * Lookup472: sp_core::ed25519::Signature **/ SpCoreEd25519Signature: '[u8;64]', /** - * Lookup446: sp_core::sr25519::Signature + * Lookup474: sp_core::sr25519::Signature **/ SpCoreSr25519Signature: '[u8;64]', /** - * Lookup447: sp_core::ecdsa::Signature + * Lookup475: sp_core::ecdsa::Signature **/ SpCoreEcdsaSignature: '[u8;65]', /** - * Lookup450: frame_system::extensions::check_spec_version::CheckSpecVersion + * Lookup478: frame_system::extensions::check_spec_version::CheckSpecVersion **/ FrameSystemExtensionsCheckSpecVersion: 'Null', /** - * Lookup451: frame_system::extensions::check_genesis::CheckGenesis + * Lookup479: frame_system::extensions::check_genesis::CheckGenesis **/ FrameSystemExtensionsCheckGenesis: 'Null', /** - * Lookup454: frame_system::extensions::check_nonce::CheckNonce + * Lookup482: frame_system::extensions::check_nonce::CheckNonce **/ FrameSystemExtensionsCheckNonce: 'Compact', /** - * Lookup455: frame_system::extensions::check_weight::CheckWeight + * Lookup483: frame_system::extensions::check_weight::CheckWeight **/ FrameSystemExtensionsCheckWeight: 'Null', /** - * Lookup456: pallet_template_transaction_payment::ChargeTransactionPayment + * Lookup484: pallet_template_transaction_payment::ChargeTransactionPayment **/ PalletTemplateTransactionPaymentChargeTransactionPayment: 'Compact', /** - * Lookup457: opal_runtime::Runtime + * Lookup485: opal_runtime::Runtime **/ OpalRuntimeRuntime: 'Null', /** - * Lookup458: pallet_ethereum::FakeTransactionFinalizer + * Lookup486: pallet_ethereum::FakeTransactionFinalizer **/ PalletEthereumFakeTransactionFinalizer: 'Null' }; --- a/tests/src/interfaces/registry.ts +++ b/tests/src/interfaces/registry.ts @@ -5,7 +5,7 @@ // this is required to allow for ambient/previous definitions import '@polkadot/types/types/registry'; -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, PalletAppPromotionCall, PalletAppPromotionError, PalletAppPromotionEvent, PalletBalancesAccountData, PalletBalancesBalanceLock, PalletBalancesCall, PalletBalancesError, PalletBalancesEvent, PalletBalancesReasons, PalletBalancesReleases, PalletBalancesReserveData, PalletCommonError, PalletCommonEvent, PalletConfigurationCall, PalletEthereumCall, PalletEthereumError, PalletEthereumEvent, PalletEthereumFakeTransactionFinalizer, PalletEthereumRawOrigin, PalletEvmAccountBasicCrossAccountIdRepr, PalletEvmCall, PalletEvmCoderSubstrateError, PalletEvmContractHelpersError, PalletEvmContractHelpersEvent, 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, PalletTransactionPaymentEvent, 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, UpDataStructsSponsorshipStateAccountId32, UpDataStructsSponsorshipStateBasicCrossAccountIdRepr, 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, OrmlTokensAccountData, OrmlTokensBalanceLock, OrmlTokensModuleCall, OrmlTokensModuleError, OrmlTokensModuleEvent, OrmlTokensReserveData, OrmlVestingModuleCall, OrmlVestingModuleError, OrmlVestingModuleEvent, OrmlVestingVestingSchedule, OrmlXtokensModuleCall, OrmlXtokensModuleError, OrmlXtokensModuleEvent, PalletAppPromotionCall, PalletAppPromotionError, PalletAppPromotionEvent, PalletBalancesAccountData, PalletBalancesBalanceLock, PalletBalancesCall, PalletBalancesError, PalletBalancesEvent, PalletBalancesReasons, PalletBalancesReleases, PalletBalancesReserveData, PalletCommonError, PalletCommonEvent, PalletConfigurationCall, PalletEthereumCall, PalletEthereumError, PalletEthereumEvent, PalletEthereumFakeTransactionFinalizer, PalletEthereumRawOrigin, PalletEvmAccountBasicCrossAccountIdRepr, PalletEvmCall, PalletEvmCoderSubstrateError, PalletEvmContractHelpersError, PalletEvmContractHelpersEvent, PalletEvmContractHelpersSponsoringModeT, PalletEvmError, PalletEvmEvent, PalletEvmMigrationCall, PalletEvmMigrationError, PalletForeignAssetsAssetIds, PalletForeignAssetsModuleAssetMetadata, PalletForeignAssetsModuleCall, PalletForeignAssetsModuleError, PalletForeignAssetsModuleEvent, PalletForeignAssetsNativeCurrency, PalletFungibleError, PalletInflationCall, PalletNonfungibleError, PalletNonfungibleItemData, PalletRefungibleError, PalletRefungibleItemData, PalletRmrkCoreCall, PalletRmrkCoreError, PalletRmrkCoreEvent, PalletRmrkEquipCall, PalletRmrkEquipError, PalletRmrkEquipEvent, PalletStructureCall, PalletStructureError, PalletStructureEvent, PalletSudoCall, PalletSudoError, PalletSudoEvent, PalletTemplateTransactionPaymentCall, PalletTemplateTransactionPaymentChargeTransactionPayment, PalletTimestampCall, PalletTransactionPaymentEvent, 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, UpDataStructsSponsorshipStateAccountId32, UpDataStructsSponsorshipStateBasicCrossAccountIdRepr, 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, XcmVersionedMultiAsset, XcmVersionedMultiAssets, XcmVersionedMultiLocation, XcmVersionedXcm } from '@polkadot/types/lookup'; declare module '@polkadot/types/types/registry' { interface InterfaceTypes { @@ -79,10 +79,19 @@ FrameSystemPhase: FrameSystemPhase; OpalRuntimeOriginCaller: OpalRuntimeOriginCaller; OpalRuntimeRuntime: OpalRuntimeRuntime; + OrmlTokensAccountData: OrmlTokensAccountData; + OrmlTokensBalanceLock: OrmlTokensBalanceLock; + OrmlTokensModuleCall: OrmlTokensModuleCall; + OrmlTokensModuleError: OrmlTokensModuleError; + OrmlTokensModuleEvent: OrmlTokensModuleEvent; + OrmlTokensReserveData: OrmlTokensReserveData; OrmlVestingModuleCall: OrmlVestingModuleCall; OrmlVestingModuleError: OrmlVestingModuleError; OrmlVestingModuleEvent: OrmlVestingModuleEvent; OrmlVestingVestingSchedule: OrmlVestingVestingSchedule; + OrmlXtokensModuleCall: OrmlXtokensModuleCall; + OrmlXtokensModuleError: OrmlXtokensModuleError; + OrmlXtokensModuleEvent: OrmlXtokensModuleEvent; PalletAppPromotionCall: PalletAppPromotionCall; PalletAppPromotionError: PalletAppPromotionError; PalletAppPromotionEvent: PalletAppPromotionEvent; @@ -112,6 +121,12 @@ PalletEvmEvent: PalletEvmEvent; PalletEvmMigrationCall: PalletEvmMigrationCall; PalletEvmMigrationError: PalletEvmMigrationError; + PalletForeignAssetsAssetIds: PalletForeignAssetsAssetIds; + PalletForeignAssetsModuleAssetMetadata: PalletForeignAssetsModuleAssetMetadata; + PalletForeignAssetsModuleCall: PalletForeignAssetsModuleCall; + PalletForeignAssetsModuleError: PalletForeignAssetsModuleError; + PalletForeignAssetsModuleEvent: PalletForeignAssetsModuleEvent; + PalletForeignAssetsNativeCurrency: PalletForeignAssetsNativeCurrency; PalletFungibleError: PalletFungibleError; PalletInflationCall: PalletInflationCall; PalletNonfungibleError: PalletNonfungibleError; @@ -252,6 +267,7 @@ XcmV2TraitsOutcome: XcmV2TraitsOutcome; XcmV2WeightLimit: XcmV2WeightLimit; XcmV2Xcm: XcmV2Xcm; + XcmVersionedMultiAsset: XcmVersionedMultiAsset; XcmVersionedMultiAssets: XcmVersionedMultiAssets; XcmVersionedMultiLocation: XcmVersionedMultiLocation; XcmVersionedXcm: XcmVersionedXcm; --- a/tests/src/interfaces/types-lookup.ts +++ b/tests/src/interfaces/types-lookup.ts @@ -351,7 +351,279 @@ readonly perPeriod: Compact; } - /** @name CumulusPalletXcmpQueueEvent (39) */ + /** @name OrmlXtokensModuleEvent (39) */ + interface OrmlXtokensModuleEvent extends Enum { + readonly isTransferredMultiAssets: boolean; + readonly asTransferredMultiAssets: { + readonly sender: AccountId32; + readonly assets: XcmV1MultiassetMultiAssets; + readonly fee: XcmV1MultiAsset; + readonly dest: XcmV1MultiLocation; + } & Struct; + readonly type: 'TransferredMultiAssets'; + } + + /** @name XcmV1MultiassetMultiAssets (40) */ + interface XcmV1MultiassetMultiAssets extends Vec {} + + /** @name XcmV1MultiAsset (42) */ + interface XcmV1MultiAsset extends Struct { + readonly id: XcmV1MultiassetAssetId; + readonly fun: XcmV1MultiassetFungibility; + } + + /** @name XcmV1MultiassetAssetId (43) */ + interface XcmV1MultiassetAssetId extends Enum { + readonly isConcrete: boolean; + readonly asConcrete: XcmV1MultiLocation; + readonly isAbstract: boolean; + readonly asAbstract: Bytes; + readonly type: 'Concrete' | 'Abstract'; + } + + /** @name XcmV1MultiLocation (44) */ + interface XcmV1MultiLocation extends Struct { + readonly parents: u8; + readonly interior: XcmV1MultilocationJunctions; + } + + /** @name XcmV1MultilocationJunctions (45) */ + interface XcmV1MultilocationJunctions extends Enum { + readonly isHere: boolean; + readonly isX1: boolean; + readonly asX1: XcmV1Junction; + readonly isX2: boolean; + readonly asX2: ITuple<[XcmV1Junction, XcmV1Junction]>; + readonly isX3: boolean; + readonly asX3: ITuple<[XcmV1Junction, XcmV1Junction, XcmV1Junction]>; + readonly isX4: boolean; + readonly asX4: ITuple<[XcmV1Junction, XcmV1Junction, XcmV1Junction, XcmV1Junction]>; + readonly isX5: boolean; + readonly asX5: ITuple<[XcmV1Junction, XcmV1Junction, XcmV1Junction, XcmV1Junction, XcmV1Junction]>; + readonly isX6: boolean; + readonly asX6: ITuple<[XcmV1Junction, XcmV1Junction, XcmV1Junction, XcmV1Junction, XcmV1Junction, XcmV1Junction]>; + readonly isX7: boolean; + readonly asX7: ITuple<[XcmV1Junction, XcmV1Junction, XcmV1Junction, XcmV1Junction, XcmV1Junction, XcmV1Junction, XcmV1Junction]>; + readonly isX8: boolean; + readonly asX8: ITuple<[XcmV1Junction, XcmV1Junction, XcmV1Junction, XcmV1Junction, XcmV1Junction, XcmV1Junction, XcmV1Junction, XcmV1Junction]>; + readonly type: 'Here' | 'X1' | 'X2' | 'X3' | 'X4' | 'X5' | 'X6' | 'X7' | 'X8'; + } + + /** @name XcmV1Junction (46) */ + interface XcmV1Junction extends Enum { + readonly isParachain: boolean; + readonly asParachain: Compact; + readonly isAccountId32: boolean; + readonly asAccountId32: { + readonly network: XcmV0JunctionNetworkId; + readonly id: U8aFixed; + } & Struct; + readonly isAccountIndex64: boolean; + readonly asAccountIndex64: { + readonly network: XcmV0JunctionNetworkId; + readonly index: Compact; + } & Struct; + readonly isAccountKey20: boolean; + readonly asAccountKey20: { + readonly network: XcmV0JunctionNetworkId; + readonly key: U8aFixed; + } & Struct; + readonly isPalletInstance: boolean; + readonly asPalletInstance: u8; + readonly isGeneralIndex: boolean; + readonly asGeneralIndex: Compact; + readonly isGeneralKey: boolean; + readonly asGeneralKey: Bytes; + readonly isOnlyChild: boolean; + readonly isPlurality: boolean; + readonly asPlurality: { + readonly id: XcmV0JunctionBodyId; + readonly part: XcmV0JunctionBodyPart; + } & Struct; + readonly type: 'Parachain' | 'AccountId32' | 'AccountIndex64' | 'AccountKey20' | 'PalletInstance' | 'GeneralIndex' | 'GeneralKey' | 'OnlyChild' | 'Plurality'; + } + + /** @name XcmV0JunctionNetworkId (48) */ + interface XcmV0JunctionNetworkId extends Enum { + readonly isAny: boolean; + readonly isNamed: boolean; + readonly asNamed: Bytes; + readonly isPolkadot: boolean; + readonly isKusama: boolean; + readonly type: 'Any' | 'Named' | 'Polkadot' | 'Kusama'; + } + + /** @name XcmV0JunctionBodyId (52) */ + interface XcmV0JunctionBodyId extends Enum { + readonly isUnit: boolean; + readonly isNamed: boolean; + readonly asNamed: Bytes; + readonly isIndex: boolean; + readonly asIndex: Compact; + readonly isExecutive: boolean; + readonly isTechnical: boolean; + readonly isLegislative: boolean; + readonly isJudicial: boolean; + readonly type: 'Unit' | 'Named' | 'Index' | 'Executive' | 'Technical' | 'Legislative' | 'Judicial'; + } + + /** @name XcmV0JunctionBodyPart (53) */ + interface XcmV0JunctionBodyPart extends Enum { + readonly isVoice: boolean; + readonly isMembers: boolean; + readonly asMembers: { + readonly count: Compact; + } & Struct; + readonly isFraction: boolean; + readonly asFraction: { + readonly nom: Compact; + readonly denom: Compact; + } & Struct; + readonly isAtLeastProportion: boolean; + readonly asAtLeastProportion: { + readonly nom: Compact; + readonly denom: Compact; + } & Struct; + readonly isMoreThanProportion: boolean; + readonly asMoreThanProportion: { + readonly nom: Compact; + readonly denom: Compact; + } & Struct; + readonly type: 'Voice' | 'Members' | 'Fraction' | 'AtLeastProportion' | 'MoreThanProportion'; + } + + /** @name XcmV1MultiassetFungibility (54) */ + interface XcmV1MultiassetFungibility extends Enum { + readonly isFungible: boolean; + readonly asFungible: Compact; + readonly isNonFungible: boolean; + readonly asNonFungible: XcmV1MultiassetAssetInstance; + readonly type: 'Fungible' | 'NonFungible'; + } + + /** @name XcmV1MultiassetAssetInstance (55) */ + interface XcmV1MultiassetAssetInstance extends Enum { + readonly isUndefined: boolean; + readonly isIndex: boolean; + readonly asIndex: Compact; + readonly isArray4: boolean; + readonly asArray4: U8aFixed; + readonly isArray8: boolean; + readonly asArray8: U8aFixed; + readonly isArray16: boolean; + readonly asArray16: U8aFixed; + readonly isArray32: boolean; + readonly asArray32: U8aFixed; + readonly isBlob: boolean; + readonly asBlob: Bytes; + readonly type: 'Undefined' | 'Index' | 'Array4' | 'Array8' | 'Array16' | 'Array32' | 'Blob'; + } + + /** @name OrmlTokensModuleEvent (58) */ + interface OrmlTokensModuleEvent extends Enum { + readonly isEndowed: boolean; + readonly asEndowed: { + readonly currencyId: PalletForeignAssetsAssetIds; + readonly who: AccountId32; + readonly amount: u128; + } & Struct; + readonly isDustLost: boolean; + readonly asDustLost: { + readonly currencyId: PalletForeignAssetsAssetIds; + readonly who: AccountId32; + readonly amount: u128; + } & Struct; + readonly isTransfer: boolean; + readonly asTransfer: { + readonly currencyId: PalletForeignAssetsAssetIds; + readonly from: AccountId32; + readonly to: AccountId32; + readonly amount: u128; + } & Struct; + readonly isReserved: boolean; + readonly asReserved: { + readonly currencyId: PalletForeignAssetsAssetIds; + readonly who: AccountId32; + readonly amount: u128; + } & Struct; + readonly isUnreserved: boolean; + readonly asUnreserved: { + readonly currencyId: PalletForeignAssetsAssetIds; + readonly who: AccountId32; + readonly amount: u128; + } & Struct; + readonly isReserveRepatriated: boolean; + readonly asReserveRepatriated: { + readonly currencyId: PalletForeignAssetsAssetIds; + readonly from: AccountId32; + readonly to: AccountId32; + readonly amount: u128; + readonly status: FrameSupportTokensMiscBalanceStatus; + } & Struct; + readonly isBalanceSet: boolean; + readonly asBalanceSet: { + readonly currencyId: PalletForeignAssetsAssetIds; + readonly who: AccountId32; + readonly free: u128; + readonly reserved: u128; + } & Struct; + readonly isTotalIssuanceSet: boolean; + readonly asTotalIssuanceSet: { + readonly currencyId: PalletForeignAssetsAssetIds; + readonly amount: u128; + } & Struct; + readonly isWithdrawn: boolean; + readonly asWithdrawn: { + readonly currencyId: PalletForeignAssetsAssetIds; + readonly who: AccountId32; + readonly amount: u128; + } & Struct; + readonly isSlashed: boolean; + readonly asSlashed: { + readonly currencyId: PalletForeignAssetsAssetIds; + readonly who: AccountId32; + readonly freeAmount: u128; + readonly reservedAmount: u128; + } & Struct; + readonly isDeposited: boolean; + readonly asDeposited: { + readonly currencyId: PalletForeignAssetsAssetIds; + readonly who: AccountId32; + readonly amount: u128; + } & Struct; + readonly isLockSet: boolean; + readonly asLockSet: { + readonly lockId: U8aFixed; + readonly currencyId: PalletForeignAssetsAssetIds; + readonly who: AccountId32; + readonly amount: u128; + } & Struct; + readonly isLockRemoved: boolean; + readonly asLockRemoved: { + readonly lockId: U8aFixed; + readonly currencyId: PalletForeignAssetsAssetIds; + readonly who: AccountId32; + } & Struct; + readonly type: 'Endowed' | 'DustLost' | 'Transfer' | 'Reserved' | 'Unreserved' | 'ReserveRepatriated' | 'BalanceSet' | 'TotalIssuanceSet' | 'Withdrawn' | 'Slashed' | 'Deposited' | 'LockSet' | 'LockRemoved'; + } + + /** @name PalletForeignAssetsAssetIds (59) */ + interface PalletForeignAssetsAssetIds extends Enum { + readonly isForeignAssetId: boolean; + readonly asForeignAssetId: u32; + readonly isNativeAssetId: boolean; + readonly asNativeAssetId: PalletForeignAssetsNativeCurrency; + readonly type: 'ForeignAssetId' | 'NativeAssetId'; + } + + /** @name PalletForeignAssetsNativeCurrency (60) */ + interface PalletForeignAssetsNativeCurrency extends Enum { + readonly isHere: boolean; + readonly isParent: boolean; + readonly type: 'Here' | 'Parent'; + } + + /** @name CumulusPalletXcmpQueueEvent (61) */ interface CumulusPalletXcmpQueueEvent extends Enum { readonly isSuccess: boolean; readonly asSuccess: { @@ -395,7 +667,7 @@ readonly type: 'Success' | 'Fail' | 'BadVersion' | 'BadFormat' | 'UpwardMessageSent' | 'XcmpMessageSent' | 'OverweightEnqueued' | 'OverweightServiced'; } - /** @name XcmV2TraitsError (41) */ + /** @name XcmV2TraitsError (63) */ interface XcmV2TraitsError extends Enum { readonly isOverflow: boolean; readonly isUnimplemented: boolean; @@ -428,7 +700,7 @@ readonly type: 'Overflow' | 'Unimplemented' | 'UntrustedReserveLocation' | 'UntrustedTeleportLocation' | 'MultiLocationFull' | 'MultiLocationNotInvertible' | 'BadOrigin' | 'InvalidLocation' | 'AssetNotFound' | 'FailedToTransactAsset' | 'NotWithdrawable' | 'LocationCannotHold' | 'ExceedsMaxMessageSize' | 'DestinationUnsupported' | 'Transport' | 'Unroutable' | 'UnknownClaim' | 'FailedToDecode' | 'MaxWeightInvalid' | 'NotHoldingFees' | 'TooExpensive' | 'Trap' | 'UnhandledXcmVersion' | 'WeightLimitReached' | 'Barrier' | 'WeightNotComputable'; } - /** @name PalletXcmEvent (43) */ + /** @name PalletXcmEvent (65) */ interface PalletXcmEvent extends Enum { readonly isAttempted: boolean; readonly asAttempted: XcmV2TraitsOutcome; @@ -465,7 +737,7 @@ readonly type: 'Attempted' | 'Sent' | 'UnexpectedResponse' | 'ResponseReady' | 'Notified' | 'NotifyOverweight' | 'NotifyDispatchError' | 'NotifyDecodeFailed' | 'InvalidResponder' | 'InvalidResponderVersion' | 'ResponseTaken' | 'AssetsTrapped' | 'VersionChangeNotified' | 'SupportedVersionChanged' | 'NotifyTargetSendFail' | 'NotifyTargetMigrationFail'; } - /** @name XcmV2TraitsOutcome (44) */ + /** @name XcmV2TraitsOutcome (66) */ interface XcmV2TraitsOutcome extends Enum { readonly isComplete: boolean; readonly asComplete: u64; @@ -474,123 +746,12 @@ readonly isError: boolean; readonly asError: XcmV2TraitsError; readonly type: 'Complete' | 'Incomplete' | 'Error'; - } - - /** @name XcmV1MultiLocation (45) */ - interface XcmV1MultiLocation extends Struct { - readonly parents: u8; - readonly interior: XcmV1MultilocationJunctions; } - /** @name XcmV1MultilocationJunctions (46) */ - interface XcmV1MultilocationJunctions extends Enum { - readonly isHere: boolean; - readonly isX1: boolean; - readonly asX1: XcmV1Junction; - readonly isX2: boolean; - readonly asX2: ITuple<[XcmV1Junction, XcmV1Junction]>; - readonly isX3: boolean; - readonly asX3: ITuple<[XcmV1Junction, XcmV1Junction, XcmV1Junction]>; - readonly isX4: boolean; - readonly asX4: ITuple<[XcmV1Junction, XcmV1Junction, XcmV1Junction, XcmV1Junction]>; - readonly isX5: boolean; - readonly asX5: ITuple<[XcmV1Junction, XcmV1Junction, XcmV1Junction, XcmV1Junction, XcmV1Junction]>; - readonly isX6: boolean; - readonly asX6: ITuple<[XcmV1Junction, XcmV1Junction, XcmV1Junction, XcmV1Junction, XcmV1Junction, XcmV1Junction]>; - readonly isX7: boolean; - readonly asX7: ITuple<[XcmV1Junction, XcmV1Junction, XcmV1Junction, XcmV1Junction, XcmV1Junction, XcmV1Junction, XcmV1Junction]>; - readonly isX8: boolean; - readonly asX8: ITuple<[XcmV1Junction, XcmV1Junction, XcmV1Junction, XcmV1Junction, XcmV1Junction, XcmV1Junction, XcmV1Junction, XcmV1Junction]>; - readonly type: 'Here' | 'X1' | 'X2' | 'X3' | 'X4' | 'X5' | 'X6' | 'X7' | 'X8'; - } - - /** @name XcmV1Junction (47) */ - interface XcmV1Junction extends Enum { - readonly isParachain: boolean; - readonly asParachain: Compact; - readonly isAccountId32: boolean; - readonly asAccountId32: { - readonly network: XcmV0JunctionNetworkId; - readonly id: U8aFixed; - } & Struct; - readonly isAccountIndex64: boolean; - readonly asAccountIndex64: { - readonly network: XcmV0JunctionNetworkId; - readonly index: Compact; - } & Struct; - readonly isAccountKey20: boolean; - readonly asAccountKey20: { - readonly network: XcmV0JunctionNetworkId; - readonly key: U8aFixed; - } & Struct; - readonly isPalletInstance: boolean; - readonly asPalletInstance: u8; - readonly isGeneralIndex: boolean; - readonly asGeneralIndex: Compact; - readonly isGeneralKey: boolean; - readonly asGeneralKey: Bytes; - readonly isOnlyChild: boolean; - readonly isPlurality: boolean; - readonly asPlurality: { - readonly id: XcmV0JunctionBodyId; - readonly part: XcmV0JunctionBodyPart; - } & Struct; - readonly type: 'Parachain' | 'AccountId32' | 'AccountIndex64' | 'AccountKey20' | 'PalletInstance' | 'GeneralIndex' | 'GeneralKey' | 'OnlyChild' | 'Plurality'; - } - - /** @name XcmV0JunctionNetworkId (49) */ - interface XcmV0JunctionNetworkId extends Enum { - readonly isAny: boolean; - readonly isNamed: boolean; - readonly asNamed: Bytes; - readonly isPolkadot: boolean; - readonly isKusama: boolean; - readonly type: 'Any' | 'Named' | 'Polkadot' | 'Kusama'; - } - - /** @name XcmV0JunctionBodyId (53) */ - interface XcmV0JunctionBodyId extends Enum { - readonly isUnit: boolean; - readonly isNamed: boolean; - readonly asNamed: Bytes; - readonly isIndex: boolean; - readonly asIndex: Compact; - readonly isExecutive: boolean; - readonly isTechnical: boolean; - readonly isLegislative: boolean; - readonly isJudicial: boolean; - readonly type: 'Unit' | 'Named' | 'Index' | 'Executive' | 'Technical' | 'Legislative' | 'Judicial'; - } - - /** @name XcmV0JunctionBodyPart (54) */ - interface XcmV0JunctionBodyPart extends Enum { - readonly isVoice: boolean; - readonly isMembers: boolean; - readonly asMembers: { - readonly count: Compact; - } & Struct; - readonly isFraction: boolean; - readonly asFraction: { - readonly nom: Compact; - readonly denom: Compact; - } & Struct; - readonly isAtLeastProportion: boolean; - readonly asAtLeastProportion: { - readonly nom: Compact; - readonly denom: Compact; - } & Struct; - readonly isMoreThanProportion: boolean; - readonly asMoreThanProportion: { - readonly nom: Compact; - readonly denom: Compact; - } & Struct; - readonly type: 'Voice' | 'Members' | 'Fraction' | 'AtLeastProportion' | 'MoreThanProportion'; - } - - /** @name XcmV2Xcm (55) */ + /** @name XcmV2Xcm (67) */ interface XcmV2Xcm extends Vec {} - /** @name XcmV2Instruction (57) */ + /** @name XcmV2Instruction (69) */ interface XcmV2Instruction extends Enum { readonly isWithdrawAsset: boolean; readonly asWithdrawAsset: XcmV1MultiassetMultiAssets; @@ -709,53 +870,8 @@ readonly isUnsubscribeVersion: boolean; readonly type: 'WithdrawAsset' | 'ReserveAssetDeposited' | 'ReceiveTeleportedAsset' | 'QueryResponse' | 'TransferAsset' | 'TransferReserveAsset' | 'Transact' | 'HrmpNewChannelOpenRequest' | 'HrmpChannelAccepted' | 'HrmpChannelClosing' | 'ClearOrigin' | 'DescendOrigin' | 'ReportError' | 'DepositAsset' | 'DepositReserveAsset' | 'ExchangeAsset' | 'InitiateReserveWithdraw' | 'InitiateTeleport' | 'QueryHolding' | 'BuyExecution' | 'RefundSurplus' | 'SetErrorHandler' | 'SetAppendix' | 'ClearError' | 'ClaimAsset' | 'Trap' | 'SubscribeVersion' | 'UnsubscribeVersion'; } - - /** @name XcmV1MultiassetMultiAssets (58) */ - interface XcmV1MultiassetMultiAssets extends Vec {} - /** @name XcmV1MultiAsset (60) */ - interface XcmV1MultiAsset extends Struct { - readonly id: XcmV1MultiassetAssetId; - readonly fun: XcmV1MultiassetFungibility; - } - - /** @name XcmV1MultiassetAssetId (61) */ - interface XcmV1MultiassetAssetId extends Enum { - readonly isConcrete: boolean; - readonly asConcrete: XcmV1MultiLocation; - readonly isAbstract: boolean; - readonly asAbstract: Bytes; - readonly type: 'Concrete' | 'Abstract'; - } - - /** @name XcmV1MultiassetFungibility (62) */ - interface XcmV1MultiassetFungibility extends Enum { - readonly isFungible: boolean; - readonly asFungible: Compact; - readonly isNonFungible: boolean; - readonly asNonFungible: XcmV1MultiassetAssetInstance; - readonly type: 'Fungible' | 'NonFungible'; - } - - /** @name XcmV1MultiassetAssetInstance (63) */ - interface XcmV1MultiassetAssetInstance extends Enum { - readonly isUndefined: boolean; - readonly isIndex: boolean; - readonly asIndex: Compact; - readonly isArray4: boolean; - readonly asArray4: U8aFixed; - readonly isArray8: boolean; - readonly asArray8: U8aFixed; - readonly isArray16: boolean; - readonly asArray16: U8aFixed; - readonly isArray32: boolean; - readonly asArray32: U8aFixed; - readonly isBlob: boolean; - readonly asBlob: Bytes; - readonly type: 'Undefined' | 'Index' | 'Array4' | 'Array8' | 'Array16' | 'Array32' | 'Blob'; - } - - /** @name XcmV2Response (66) */ + /** @name XcmV2Response (70) */ interface XcmV2Response extends Enum { readonly isNull: boolean; readonly isAssets: boolean; @@ -767,7 +883,7 @@ readonly type: 'Null' | 'Assets' | 'ExecutionResult' | 'Version'; } - /** @name XcmV0OriginKind (69) */ + /** @name XcmV0OriginKind (73) */ interface XcmV0OriginKind extends Enum { readonly isNative: boolean; readonly isSovereignAccount: boolean; @@ -776,12 +892,12 @@ readonly type: 'Native' | 'SovereignAccount' | 'Superuser' | 'Xcm'; } - /** @name XcmDoubleEncoded (70) */ + /** @name XcmDoubleEncoded (74) */ interface XcmDoubleEncoded extends Struct { readonly encoded: Bytes; } - /** @name XcmV1MultiassetMultiAssetFilter (71) */ + /** @name XcmV1MultiassetMultiAssetFilter (75) */ interface XcmV1MultiassetMultiAssetFilter extends Enum { readonly isDefinite: boolean; readonly asDefinite: XcmV1MultiassetMultiAssets; @@ -790,7 +906,7 @@ readonly type: 'Definite' | 'Wild'; } - /** @name XcmV1MultiassetWildMultiAsset (72) */ + /** @name XcmV1MultiassetWildMultiAsset (76) */ interface XcmV1MultiassetWildMultiAsset extends Enum { readonly isAll: boolean; readonly isAllOf: boolean; @@ -801,14 +917,14 @@ readonly type: 'All' | 'AllOf'; } - /** @name XcmV1MultiassetWildFungibility (73) */ + /** @name XcmV1MultiassetWildFungibility (77) */ interface XcmV1MultiassetWildFungibility extends Enum { readonly isFungible: boolean; readonly isNonFungible: boolean; readonly type: 'Fungible' | 'NonFungible'; } - /** @name XcmV2WeightLimit (74) */ + /** @name XcmV2WeightLimit (78) */ interface XcmV2WeightLimit extends Enum { readonly isUnlimited: boolean; readonly isLimited: boolean; @@ -816,7 +932,7 @@ readonly type: 'Unlimited' | 'Limited'; } - /** @name XcmVersionedMultiAssets (76) */ + /** @name XcmVersionedMultiAssets (80) */ interface XcmVersionedMultiAssets extends Enum { readonly isV0: boolean; readonly asV0: Vec; @@ -825,7 +941,7 @@ readonly type: 'V0' | 'V1'; } - /** @name XcmV0MultiAsset (78) */ + /** @name XcmV0MultiAsset (82) */ interface XcmV0MultiAsset extends Enum { readonly isNone: boolean; readonly isAll: boolean; @@ -870,7 +986,7 @@ readonly type: 'None' | 'All' | 'AllFungible' | 'AllNonFungible' | 'AllAbstractFungible' | 'AllAbstractNonFungible' | 'AllConcreteFungible' | 'AllConcreteNonFungible' | 'AbstractFungible' | 'AbstractNonFungible' | 'ConcreteFungible' | 'ConcreteNonFungible'; } - /** @name XcmV0MultiLocation (79) */ + /** @name XcmV0MultiLocation (83) */ interface XcmV0MultiLocation extends Enum { readonly isNull: boolean; readonly isX1: boolean; @@ -892,7 +1008,7 @@ readonly type: 'Null' | 'X1' | 'X2' | 'X3' | 'X4' | 'X5' | 'X6' | 'X7' | 'X8'; } - /** @name XcmV0Junction (80) */ + /** @name XcmV0Junction (84) */ interface XcmV0Junction extends Enum { readonly isParent: boolean; readonly isParachain: boolean; @@ -927,7 +1043,7 @@ readonly type: 'Parent' | 'Parachain' | 'AccountId32' | 'AccountIndex64' | 'AccountKey20' | 'PalletInstance' | 'GeneralIndex' | 'GeneralKey' | 'OnlyChild' | 'Plurality'; } - /** @name XcmVersionedMultiLocation (81) */ + /** @name XcmVersionedMultiLocation (85) */ interface XcmVersionedMultiLocation extends Enum { readonly isV0: boolean; readonly asV0: XcmV0MultiLocation; @@ -936,7 +1052,7 @@ readonly type: 'V0' | 'V1'; } - /** @name CumulusPalletXcmEvent (82) */ + /** @name CumulusPalletXcmEvent (86) */ interface CumulusPalletXcmEvent extends Enum { readonly isInvalidFormat: boolean; readonly asInvalidFormat: U8aFixed; @@ -947,7 +1063,7 @@ readonly type: 'InvalidFormat' | 'UnsupportedVersion' | 'ExecutedDownward'; } - /** @name CumulusPalletDmpQueueEvent (83) */ + /** @name CumulusPalletDmpQueueEvent (87) */ interface CumulusPalletDmpQueueEvent extends Enum { readonly isInvalidFormat: boolean; readonly asInvalidFormat: { @@ -982,7 +1098,7 @@ readonly type: 'InvalidFormat' | 'UnsupportedVersion' | 'ExecutedDownward' | 'WeightExhausted' | 'OverweightEnqueued' | 'OverweightServiced'; } - /** @name PalletUniqueRawEvent (84) */ + /** @name PalletUniqueRawEvent (88) */ interface PalletUniqueRawEvent extends Enum { readonly isCollectionSponsorRemoved: boolean; readonly asCollectionSponsorRemoved: u32; @@ -1007,7 +1123,7 @@ readonly type: 'CollectionSponsorRemoved' | 'CollectionAdminAdded' | 'CollectionOwnedChanged' | 'CollectionSponsorSet' | 'SponsorshipConfirmed' | 'CollectionAdminRemoved' | 'AllowListAddressRemoved' | 'AllowListAddressAdded' | 'CollectionLimitSet' | 'CollectionPermissionSet'; } - /** @name PalletEvmAccountBasicCrossAccountIdRepr (85) */ + /** @name PalletEvmAccountBasicCrossAccountIdRepr (89) */ interface PalletEvmAccountBasicCrossAccountIdRepr extends Enum { readonly isSubstrate: boolean; readonly asSubstrate: AccountId32; @@ -1016,7 +1132,7 @@ readonly type: 'Substrate' | 'Ethereum'; } - /** @name PalletUniqueSchedulerEvent (88) */ + /** @name PalletUniqueSchedulerEvent (92) */ interface PalletUniqueSchedulerEvent extends Enum { readonly isScheduled: boolean; readonly asScheduled: { @@ -1043,14 +1159,14 @@ readonly type: 'Scheduled' | 'Canceled' | 'Dispatched' | 'CallLookupFailed'; } - /** @name FrameSupportScheduleLookupError (91) */ + /** @name FrameSupportScheduleLookupError (95) */ interface FrameSupportScheduleLookupError extends Enum { readonly isUnknown: boolean; readonly isBadFormat: boolean; readonly type: 'Unknown' | 'BadFormat'; } - /** @name PalletCommonEvent (92) */ + /** @name PalletCommonEvent (96) */ interface PalletCommonEvent extends Enum { readonly isCollectionCreated: boolean; readonly asCollectionCreated: ITuple<[u32, u8, AccountId32]>; @@ -1077,14 +1193,14 @@ readonly type: 'CollectionCreated' | 'CollectionDestroyed' | 'ItemCreated' | 'ItemDestroyed' | 'Transfer' | 'Approved' | 'CollectionPropertySet' | 'CollectionPropertyDeleted' | 'TokenPropertySet' | 'TokenPropertyDeleted' | 'PropertyPermissionSet'; } - /** @name PalletStructureEvent (95) */ + /** @name PalletStructureEvent (99) */ interface PalletStructureEvent extends Enum { readonly isExecuted: boolean; readonly asExecuted: Result; readonly type: 'Executed'; } - /** @name PalletRmrkCoreEvent (96) */ + /** @name PalletRmrkCoreEvent (100) */ interface PalletRmrkCoreEvent extends Enum { readonly isCollectionCreated: boolean; readonly asCollectionCreated: { @@ -1174,7 +1290,7 @@ readonly type: 'CollectionCreated' | 'CollectionDestroyed' | 'IssuerChanged' | 'CollectionLocked' | 'NftMinted' | 'NftBurned' | 'NftSent' | 'NftAccepted' | 'NftRejected' | 'PropertySet' | 'ResourceAdded' | 'ResourceRemoval' | 'ResourceAccepted' | 'ResourceRemovalAccepted' | 'PrioritySet'; } - /** @name RmrkTraitsNftAccountIdOrCollectionNftTuple (97) */ + /** @name RmrkTraitsNftAccountIdOrCollectionNftTuple (101) */ interface RmrkTraitsNftAccountIdOrCollectionNftTuple extends Enum { readonly isAccountId: boolean; readonly asAccountId: AccountId32; @@ -1183,7 +1299,7 @@ readonly type: 'AccountId' | 'CollectionAndNftTuple'; } - /** @name PalletRmrkEquipEvent (102) */ + /** @name PalletRmrkEquipEvent (106) */ interface PalletRmrkEquipEvent extends Enum { readonly isBaseCreated: boolean; readonly asBaseCreated: { @@ -1198,7 +1314,7 @@ readonly type: 'BaseCreated' | 'EquippablesUpdated'; } - /** @name PalletAppPromotionEvent (103) */ + /** @name PalletAppPromotionEvent (107) */ interface PalletAppPromotionEvent extends Enum { readonly isStakingRecalculation: boolean; readonly asStakingRecalculation: ITuple<[AccountId32, u128, u128]>; @@ -1211,7 +1327,42 @@ readonly type: 'StakingRecalculation' | 'Stake' | 'Unstake' | 'SetAdmin'; } - /** @name PalletEvmEvent (104) */ + /** @name PalletForeignAssetsModuleEvent (108) */ + interface PalletForeignAssetsModuleEvent extends Enum { + readonly isForeignAssetRegistered: boolean; + readonly asForeignAssetRegistered: { + readonly assetId: u32; + readonly assetAddress: XcmV1MultiLocation; + readonly metadata: PalletForeignAssetsModuleAssetMetadata; + } & Struct; + readonly isForeignAssetUpdated: boolean; + readonly asForeignAssetUpdated: { + readonly assetId: u32; + readonly assetAddress: XcmV1MultiLocation; + readonly metadata: PalletForeignAssetsModuleAssetMetadata; + } & Struct; + readonly isAssetRegistered: boolean; + readonly asAssetRegistered: { + readonly assetId: PalletForeignAssetsAssetIds; + readonly metadata: PalletForeignAssetsModuleAssetMetadata; + } & Struct; + readonly isAssetUpdated: boolean; + readonly asAssetUpdated: { + readonly assetId: PalletForeignAssetsAssetIds; + readonly metadata: PalletForeignAssetsModuleAssetMetadata; + } & Struct; + readonly type: 'ForeignAssetRegistered' | 'ForeignAssetUpdated' | 'AssetRegistered' | 'AssetUpdated'; + } + + /** @name PalletForeignAssetsModuleAssetMetadata (109) */ + interface PalletForeignAssetsModuleAssetMetadata extends Struct { + readonly name: Bytes; + readonly symbol: Bytes; + readonly decimals: u8; + readonly minimalBalance: u128; + } + + /** @name PalletEvmEvent (110) */ interface PalletEvmEvent extends Enum { readonly isLog: boolean; readonly asLog: EthereumLog; @@ -1230,21 +1381,21 @@ readonly type: 'Log' | 'Created' | 'CreatedFailed' | 'Executed' | 'ExecutedFailed' | 'BalanceDeposit' | 'BalanceWithdraw'; } - /** @name EthereumLog (105) */ + /** @name EthereumLog (111) */ interface EthereumLog extends Struct { readonly address: H160; readonly topics: Vec; readonly data: Bytes; } - /** @name PalletEthereumEvent (109) */ + /** @name PalletEthereumEvent (115) */ interface PalletEthereumEvent extends Enum { readonly isExecuted: boolean; readonly asExecuted: ITuple<[H160, H160, H256, EvmCoreErrorExitReason]>; readonly type: 'Executed'; } - /** @name EvmCoreErrorExitReason (110) */ + /** @name EvmCoreErrorExitReason (116) */ interface EvmCoreErrorExitReason extends Enum { readonly isSucceed: boolean; readonly asSucceed: EvmCoreErrorExitSucceed; @@ -1257,7 +1408,7 @@ readonly type: 'Succeed' | 'Error' | 'Revert' | 'Fatal'; } - /** @name EvmCoreErrorExitSucceed (111) */ + /** @name EvmCoreErrorExitSucceed (117) */ interface EvmCoreErrorExitSucceed extends Enum { readonly isStopped: boolean; readonly isReturned: boolean; @@ -1265,7 +1416,7 @@ readonly type: 'Stopped' | 'Returned' | 'Suicided'; } - /** @name EvmCoreErrorExitError (112) */ + /** @name EvmCoreErrorExitError (118) */ interface EvmCoreErrorExitError extends Enum { readonly isStackUnderflow: boolean; readonly isStackOverflow: boolean; @@ -1286,13 +1437,13 @@ readonly type: 'StackUnderflow' | 'StackOverflow' | 'InvalidJump' | 'InvalidRange' | 'DesignatedInvalid' | 'CallTooDeep' | 'CreateCollision' | 'CreateContractLimit' | 'OutOfOffset' | 'OutOfGas' | 'OutOfFund' | 'PcUnderflow' | 'CreateEmpty' | 'Other' | 'InvalidCode'; } - /** @name EvmCoreErrorExitRevert (115) */ + /** @name EvmCoreErrorExitRevert (121) */ interface EvmCoreErrorExitRevert extends Enum { readonly isReverted: boolean; readonly type: 'Reverted'; } - /** @name EvmCoreErrorExitFatal (116) */ + /** @name EvmCoreErrorExitFatal (122) */ interface EvmCoreErrorExitFatal extends Enum { readonly isNotSupported: boolean; readonly isUnhandledInterrupt: boolean; @@ -1303,7 +1454,7 @@ readonly type: 'NotSupported' | 'UnhandledInterrupt' | 'CallErrorAsFatal' | 'Other'; } - /** @name PalletEvmContractHelpersEvent (117) */ + /** @name PalletEvmContractHelpersEvent (123) */ interface PalletEvmContractHelpersEvent extends Enum { readonly isContractSponsorSet: boolean; readonly asContractSponsorSet: ITuple<[H160, AccountId32]>; @@ -1314,7 +1465,7 @@ readonly type: 'ContractSponsorSet' | 'ContractSponsorshipConfirmed' | 'ContractSponsorRemoved'; } - /** @name FrameSystemPhase (118) */ + /** @name FrameSystemPhase (124) */ interface FrameSystemPhase extends Enum { readonly isApplyExtrinsic: boolean; readonly asApplyExtrinsic: u32; @@ -1323,13 +1474,13 @@ readonly type: 'ApplyExtrinsic' | 'Finalization' | 'Initialization'; } - /** @name FrameSystemLastRuntimeUpgradeInfo (120) */ + /** @name FrameSystemLastRuntimeUpgradeInfo (126) */ interface FrameSystemLastRuntimeUpgradeInfo extends Struct { readonly specVersion: Compact; readonly specName: Text; } - /** @name FrameSystemCall (121) */ + /** @name FrameSystemCall (127) */ interface FrameSystemCall extends Enum { readonly isFillBlock: boolean; readonly asFillBlock: { @@ -1371,21 +1522,21 @@ readonly type: 'FillBlock' | 'Remark' | 'SetHeapPages' | 'SetCode' | 'SetCodeWithoutChecks' | 'SetStorage' | 'KillStorage' | 'KillPrefix' | 'RemarkWithEvent'; } - /** @name FrameSystemLimitsBlockWeights (126) */ + /** @name FrameSystemLimitsBlockWeights (132) */ interface FrameSystemLimitsBlockWeights extends Struct { readonly baseBlock: u64; readonly maxBlock: u64; readonly perClass: FrameSupportWeightsPerDispatchClassWeightsPerClass; } - /** @name FrameSupportWeightsPerDispatchClassWeightsPerClass (127) */ + /** @name FrameSupportWeightsPerDispatchClassWeightsPerClass (133) */ interface FrameSupportWeightsPerDispatchClassWeightsPerClass extends Struct { readonly normal: FrameSystemLimitsWeightsPerClass; readonly operational: FrameSystemLimitsWeightsPerClass; readonly mandatory: FrameSystemLimitsWeightsPerClass; } - /** @name FrameSystemLimitsWeightsPerClass (128) */ + /** @name FrameSystemLimitsWeightsPerClass (134) */ interface FrameSystemLimitsWeightsPerClass extends Struct { readonly baseExtrinsic: u64; readonly maxExtrinsic: Option; @@ -1393,25 +1544,25 @@ readonly reserved: Option; } - /** @name FrameSystemLimitsBlockLength (130) */ + /** @name FrameSystemLimitsBlockLength (136) */ interface FrameSystemLimitsBlockLength extends Struct { readonly max: FrameSupportWeightsPerDispatchClassU32; } - /** @name FrameSupportWeightsPerDispatchClassU32 (131) */ + /** @name FrameSupportWeightsPerDispatchClassU32 (137) */ interface FrameSupportWeightsPerDispatchClassU32 extends Struct { readonly normal: u32; readonly operational: u32; readonly mandatory: u32; } - /** @name FrameSupportWeightsRuntimeDbWeight (132) */ + /** @name FrameSupportWeightsRuntimeDbWeight (138) */ interface FrameSupportWeightsRuntimeDbWeight extends Struct { readonly read: u64; readonly write: u64; } - /** @name SpVersionRuntimeVersion (133) */ + /** @name SpVersionRuntimeVersion (139) */ interface SpVersionRuntimeVersion extends Struct { readonly specName: Text; readonly implName: Text; @@ -1423,7 +1574,7 @@ readonly stateVersion: u8; } - /** @name FrameSystemError (138) */ + /** @name FrameSystemError (144) */ interface FrameSystemError extends Enum { readonly isInvalidSpecName: boolean; readonly isSpecVersionNeedsToIncrease: boolean; @@ -1434,7 +1585,7 @@ readonly type: 'InvalidSpecName' | 'SpecVersionNeedsToIncrease' | 'FailedToExtractRuntimeVersion' | 'NonDefaultComposite' | 'NonZeroRefCount' | 'CallFiltered'; } - /** @name PolkadotPrimitivesV2PersistedValidationData (139) */ + /** @name PolkadotPrimitivesV2PersistedValidationData (145) */ interface PolkadotPrimitivesV2PersistedValidationData extends Struct { readonly parentHead: Bytes; readonly relayParentNumber: u32; @@ -1442,18 +1593,18 @@ readonly maxPovSize: u32; } - /** @name PolkadotPrimitivesV2UpgradeRestriction (142) */ + /** @name PolkadotPrimitivesV2UpgradeRestriction (148) */ interface PolkadotPrimitivesV2UpgradeRestriction extends Enum { readonly isPresent: boolean; readonly type: 'Present'; } - /** @name SpTrieStorageProof (143) */ + /** @name SpTrieStorageProof (149) */ interface SpTrieStorageProof extends Struct { readonly trieNodes: BTreeSet; } - /** @name CumulusPalletParachainSystemRelayStateSnapshotMessagingStateSnapshot (145) */ + /** @name CumulusPalletParachainSystemRelayStateSnapshotMessagingStateSnapshot (151) */ interface CumulusPalletParachainSystemRelayStateSnapshotMessagingStateSnapshot extends Struct { readonly dmqMqcHead: H256; readonly relayDispatchQueueSize: ITuple<[u32, u32]>; @@ -1461,7 +1612,7 @@ readonly egressChannels: Vec>; } - /** @name PolkadotPrimitivesV2AbridgedHrmpChannel (148) */ + /** @name PolkadotPrimitivesV2AbridgedHrmpChannel (154) */ interface PolkadotPrimitivesV2AbridgedHrmpChannel extends Struct { readonly maxCapacity: u32; readonly maxTotalSize: u32; @@ -1471,7 +1622,7 @@ readonly mqcHead: Option; } - /** @name PolkadotPrimitivesV2AbridgedHostConfiguration (149) */ + /** @name PolkadotPrimitivesV2AbridgedHostConfiguration (155) */ interface PolkadotPrimitivesV2AbridgedHostConfiguration extends Struct { readonly maxCodeSize: u32; readonly maxHeadDataSize: u32; @@ -1484,13 +1635,13 @@ readonly validationUpgradeDelay: u32; } - /** @name PolkadotCorePrimitivesOutboundHrmpMessage (155) */ + /** @name PolkadotCorePrimitivesOutboundHrmpMessage (161) */ interface PolkadotCorePrimitivesOutboundHrmpMessage extends Struct { readonly recipient: u32; readonly data: Bytes; } - /** @name CumulusPalletParachainSystemCall (156) */ + /** @name CumulusPalletParachainSystemCall (162) */ interface CumulusPalletParachainSystemCall extends Enum { readonly isSetValidationData: boolean; readonly asSetValidationData: { @@ -1511,7 +1662,7 @@ readonly type: 'SetValidationData' | 'SudoSendUpwardMessage' | 'AuthorizeUpgrade' | 'EnactAuthorizedUpgrade'; } - /** @name CumulusPrimitivesParachainInherentParachainInherentData (157) */ + /** @name CumulusPrimitivesParachainInherentParachainInherentData (163) */ interface CumulusPrimitivesParachainInherentParachainInherentData extends Struct { readonly validationData: PolkadotPrimitivesV2PersistedValidationData; readonly relayChainState: SpTrieStorageProof; @@ -1519,19 +1670,19 @@ readonly horizontalMessages: BTreeMap>; } - /** @name PolkadotCorePrimitivesInboundDownwardMessage (159) */ + /** @name PolkadotCorePrimitivesInboundDownwardMessage (165) */ interface PolkadotCorePrimitivesInboundDownwardMessage extends Struct { readonly sentAt: u32; readonly msg: Bytes; } - /** @name PolkadotCorePrimitivesInboundHrmpMessage (162) */ + /** @name PolkadotCorePrimitivesInboundHrmpMessage (168) */ interface PolkadotCorePrimitivesInboundHrmpMessage extends Struct { readonly sentAt: u32; readonly data: Bytes; } - /** @name CumulusPalletParachainSystemError (165) */ + /** @name CumulusPalletParachainSystemError (171) */ interface CumulusPalletParachainSystemError extends Enum { readonly isOverlappingUpgrades: boolean; readonly isProhibitedByPolkadot: boolean; @@ -1544,14 +1695,14 @@ readonly type: 'OverlappingUpgrades' | 'ProhibitedByPolkadot' | 'TooBig' | 'ValidationDataNotAvailable' | 'HostConfigurationNotAvailable' | 'NotScheduled' | 'NothingAuthorized' | 'Unauthorized'; } - /** @name PalletBalancesBalanceLock (167) */ + /** @name PalletBalancesBalanceLock (173) */ interface PalletBalancesBalanceLock extends Struct { readonly id: U8aFixed; readonly amount: u128; readonly reasons: PalletBalancesReasons; } - /** @name PalletBalancesReasons (168) */ + /** @name PalletBalancesReasons (174) */ interface PalletBalancesReasons extends Enum { readonly isFee: boolean; readonly isMisc: boolean; @@ -1559,20 +1710,20 @@ readonly type: 'Fee' | 'Misc' | 'All'; } - /** @name PalletBalancesReserveData (171) */ + /** @name PalletBalancesReserveData (177) */ interface PalletBalancesReserveData extends Struct { readonly id: U8aFixed; readonly amount: u128; } - /** @name PalletBalancesReleases (173) */ + /** @name PalletBalancesReleases (179) */ interface PalletBalancesReleases extends Enum { readonly isV100: boolean; readonly isV200: boolean; readonly type: 'V100' | 'V200'; } - /** @name PalletBalancesCall (174) */ + /** @name PalletBalancesCall (180) */ interface PalletBalancesCall extends Enum { readonly isTransfer: boolean; readonly asTransfer: { @@ -1609,7 +1760,7 @@ readonly type: 'Transfer' | 'SetBalance' | 'ForceTransfer' | 'TransferKeepAlive' | 'TransferAll' | 'ForceUnreserve'; } - /** @name PalletBalancesError (177) */ + /** @name PalletBalancesError (183) */ interface PalletBalancesError extends Enum { readonly isVestingBalance: boolean; readonly isLiquidityRestrictions: boolean; @@ -1622,7 +1773,7 @@ readonly type: 'VestingBalance' | 'LiquidityRestrictions' | 'InsufficientBalance' | 'ExistentialDeposit' | 'KeepAlive' | 'ExistingVestingSchedule' | 'DeadAccount' | 'TooManyReserves'; } - /** @name PalletTimestampCall (179) */ + /** @name PalletTimestampCall (185) */ interface PalletTimestampCall extends Enum { readonly isSet: boolean; readonly asSet: { @@ -1631,14 +1782,14 @@ readonly type: 'Set'; } - /** @name PalletTransactionPaymentReleases (181) */ + /** @name PalletTransactionPaymentReleases (187) */ interface PalletTransactionPaymentReleases extends Enum { readonly isV1Ancient: boolean; readonly isV2: boolean; readonly type: 'V1Ancient' | 'V2'; } - /** @name PalletTreasuryProposal (182) */ + /** @name PalletTreasuryProposal (188) */ interface PalletTreasuryProposal extends Struct { readonly proposer: AccountId32; readonly value: u128; @@ -1646,7 +1797,7 @@ readonly bond: u128; } - /** @name PalletTreasuryCall (185) */ + /** @name PalletTreasuryCall (191) */ interface PalletTreasuryCall extends Enum { readonly isProposeSpend: boolean; readonly asProposeSpend: { @@ -1673,10 +1824,10 @@ readonly type: 'ProposeSpend' | 'RejectProposal' | 'ApproveProposal' | 'Spend' | 'RemoveApproval'; } - /** @name FrameSupportPalletId (188) */ + /** @name FrameSupportPalletId (194) */ interface FrameSupportPalletId extends U8aFixed {} - /** @name PalletTreasuryError (189) */ + /** @name PalletTreasuryError (195) */ interface PalletTreasuryError extends Enum { readonly isInsufficientProposersBalance: boolean; readonly isInvalidIndex: boolean; @@ -1686,7 +1837,7 @@ readonly type: 'InsufficientProposersBalance' | 'InvalidIndex' | 'TooManyApprovals' | 'InsufficientPermission' | 'ProposalNotApproved'; } - /** @name PalletSudoCall (190) */ + /** @name PalletSudoCall (196) */ interface PalletSudoCall extends Enum { readonly isSudo: boolean; readonly asSudo: { @@ -1709,7 +1860,7 @@ readonly type: 'Sudo' | 'SudoUncheckedWeight' | 'SetKey' | 'SudoAs'; } - /** @name OrmlVestingModuleCall (192) */ + /** @name OrmlVestingModuleCall (198) */ interface OrmlVestingModuleCall extends Enum { readonly isClaim: boolean; readonly isVestedTransfer: boolean; @@ -1729,7 +1880,100 @@ readonly type: 'Claim' | 'VestedTransfer' | 'UpdateVestingSchedules' | 'ClaimFor'; } - /** @name CumulusPalletXcmpQueueCall (194) */ + /** @name OrmlXtokensModuleCall (200) */ + interface OrmlXtokensModuleCall extends Enum { + readonly isTransfer: boolean; + readonly asTransfer: { + readonly currencyId: PalletForeignAssetsAssetIds; + readonly amount: u128; + readonly dest: XcmVersionedMultiLocation; + readonly destWeight: u64; + } & Struct; + readonly isTransferMultiasset: boolean; + readonly asTransferMultiasset: { + readonly asset: XcmVersionedMultiAsset; + readonly dest: XcmVersionedMultiLocation; + readonly destWeight: u64; + } & Struct; + readonly isTransferWithFee: boolean; + readonly asTransferWithFee: { + readonly currencyId: PalletForeignAssetsAssetIds; + readonly amount: u128; + readonly fee: u128; + readonly dest: XcmVersionedMultiLocation; + readonly destWeight: u64; + } & Struct; + readonly isTransferMultiassetWithFee: boolean; + readonly asTransferMultiassetWithFee: { + readonly asset: XcmVersionedMultiAsset; + readonly fee: XcmVersionedMultiAsset; + readonly dest: XcmVersionedMultiLocation; + readonly destWeight: u64; + } & Struct; + readonly isTransferMulticurrencies: boolean; + readonly asTransferMulticurrencies: { + readonly currencies: Vec>; + readonly feeItem: u32; + readonly dest: XcmVersionedMultiLocation; + readonly destWeight: u64; + } & Struct; + readonly isTransferMultiassets: boolean; + readonly asTransferMultiassets: { + readonly assets: XcmVersionedMultiAssets; + readonly feeItem: u32; + readonly dest: XcmVersionedMultiLocation; + readonly destWeight: u64; + } & Struct; + readonly type: 'Transfer' | 'TransferMultiasset' | 'TransferWithFee' | 'TransferMultiassetWithFee' | 'TransferMulticurrencies' | 'TransferMultiassets'; + } + + /** @name XcmVersionedMultiAsset (201) */ + interface XcmVersionedMultiAsset extends Enum { + readonly isV0: boolean; + readonly asV0: XcmV0MultiAsset; + readonly isV1: boolean; + readonly asV1: XcmV1MultiAsset; + readonly type: 'V0' | 'V1'; + } + + /** @name OrmlTokensModuleCall (204) */ + interface OrmlTokensModuleCall extends Enum { + readonly isTransfer: boolean; + readonly asTransfer: { + readonly dest: MultiAddress; + readonly currencyId: PalletForeignAssetsAssetIds; + readonly amount: Compact; + } & Struct; + readonly isTransferAll: boolean; + readonly asTransferAll: { + readonly dest: MultiAddress; + readonly currencyId: PalletForeignAssetsAssetIds; + readonly keepAlive: bool; + } & Struct; + readonly isTransferKeepAlive: boolean; + readonly asTransferKeepAlive: { + readonly dest: MultiAddress; + readonly currencyId: PalletForeignAssetsAssetIds; + readonly amount: Compact; + } & Struct; + readonly isForceTransfer: boolean; + readonly asForceTransfer: { + readonly source: MultiAddress; + readonly dest: MultiAddress; + readonly currencyId: PalletForeignAssetsAssetIds; + readonly amount: Compact; + } & Struct; + readonly isSetBalance: boolean; + readonly asSetBalance: { + readonly who: MultiAddress; + readonly currencyId: PalletForeignAssetsAssetIds; + readonly newFree: Compact; + readonly newReserved: Compact; + } & Struct; + readonly type: 'Transfer' | 'TransferAll' | 'TransferKeepAlive' | 'ForceTransfer' | 'SetBalance'; + } + + /** @name CumulusPalletXcmpQueueCall (205) */ interface CumulusPalletXcmpQueueCall extends Enum { readonly isServiceOverweight: boolean; readonly asServiceOverweight: { @@ -1765,7 +2009,7 @@ readonly type: 'ServiceOverweight' | 'SuspendXcmExecution' | 'ResumeXcmExecution' | 'UpdateSuspendThreshold' | 'UpdateDropThreshold' | 'UpdateResumeThreshold' | 'UpdateThresholdWeight' | 'UpdateWeightRestrictDecay' | 'UpdateXcmpMaxIndividualWeight'; } - /** @name PalletXcmCall (195) */ + /** @name PalletXcmCall (206) */ interface PalletXcmCall extends Enum { readonly isSend: boolean; readonly asSend: { @@ -1827,7 +2071,7 @@ readonly type: 'Send' | 'TeleportAssets' | 'ReserveTransferAssets' | 'Execute' | 'ForceXcmVersion' | 'ForceDefaultXcmVersion' | 'ForceSubscribeVersionNotify' | 'ForceUnsubscribeVersionNotify' | 'LimitedReserveTransferAssets' | 'LimitedTeleportAssets'; } - /** @name XcmVersionedXcm (196) */ + /** @name XcmVersionedXcm (207) */ interface XcmVersionedXcm extends Enum { readonly isV0: boolean; readonly asV0: XcmV0Xcm; @@ -1838,7 +2082,7 @@ readonly type: 'V0' | 'V1' | 'V2'; } - /** @name XcmV0Xcm (197) */ + /** @name XcmV0Xcm (208) */ interface XcmV0Xcm extends Enum { readonly isWithdrawAsset: boolean; readonly asWithdrawAsset: { @@ -1901,7 +2145,7 @@ readonly type: 'WithdrawAsset' | 'ReserveAssetDeposit' | 'TeleportAsset' | 'QueryResponse' | 'TransferAsset' | 'TransferReserveAsset' | 'Transact' | 'HrmpNewChannelOpenRequest' | 'HrmpChannelAccepted' | 'HrmpChannelClosing' | 'RelayedFrom'; } - /** @name XcmV0Order (199) */ + /** @name XcmV0Order (210) */ interface XcmV0Order extends Enum { readonly isNull: boolean; readonly isDepositAsset: boolean; @@ -1949,14 +2193,14 @@ readonly type: 'Null' | 'DepositAsset' | 'DepositReserveAsset' | 'ExchangeAsset' | 'InitiateReserveWithdraw' | 'InitiateTeleport' | 'QueryHolding' | 'BuyExecution'; } - /** @name XcmV0Response (201) */ + /** @name XcmV0Response (212) */ interface XcmV0Response extends Enum { readonly isAssets: boolean; readonly asAssets: Vec; readonly type: 'Assets'; } - /** @name XcmV1Xcm (202) */ + /** @name XcmV1Xcm (213) */ interface XcmV1Xcm extends Enum { readonly isWithdrawAsset: boolean; readonly asWithdrawAsset: { @@ -2025,7 +2269,7 @@ readonly type: 'WithdrawAsset' | 'ReserveAssetDeposited' | 'ReceiveTeleportedAsset' | 'QueryResponse' | 'TransferAsset' | 'TransferReserveAsset' | 'Transact' | 'HrmpNewChannelOpenRequest' | 'HrmpChannelAccepted' | 'HrmpChannelClosing' | 'RelayedFrom' | 'SubscribeVersion' | 'UnsubscribeVersion'; } - /** @name XcmV1Order (204) */ + /** @name XcmV1Order (215) */ interface XcmV1Order extends Enum { readonly isNoop: boolean; readonly isDepositAsset: boolean; @@ -2075,7 +2319,7 @@ readonly type: 'Noop' | 'DepositAsset' | 'DepositReserveAsset' | 'ExchangeAsset' | 'InitiateReserveWithdraw' | 'InitiateTeleport' | 'QueryHolding' | 'BuyExecution'; } - /** @name XcmV1Response (206) */ + /** @name XcmV1Response (217) */ interface XcmV1Response extends Enum { readonly isAssets: boolean; readonly asAssets: XcmV1MultiassetMultiAssets; @@ -2084,10 +2328,10 @@ readonly type: 'Assets' | 'Version'; } - /** @name CumulusPalletXcmCall (220) */ + /** @name CumulusPalletXcmCall (231) */ type CumulusPalletXcmCall = Null; - /** @name CumulusPalletDmpQueueCall (221) */ + /** @name CumulusPalletDmpQueueCall (232) */ interface CumulusPalletDmpQueueCall extends Enum { readonly isServiceOverweight: boolean; readonly asServiceOverweight: { @@ -2097,7 +2341,7 @@ readonly type: 'ServiceOverweight'; } - /** @name PalletInflationCall (222) */ + /** @name PalletInflationCall (233) */ interface PalletInflationCall extends Enum { readonly isStartInflation: boolean; readonly asStartInflation: { @@ -2106,7 +2350,7 @@ readonly type: 'StartInflation'; } - /** @name PalletUniqueCall (223) */ + /** @name PalletUniqueCall (234) */ interface PalletUniqueCall extends Enum { readonly isCreateCollection: boolean; readonly asCreateCollection: { @@ -2264,7 +2508,7 @@ readonly type: 'CreateCollection' | 'CreateCollectionEx' | 'DestroyCollection' | 'AddToAllowList' | 'RemoveFromAllowList' | 'ChangeCollectionOwner' | 'AddCollectionAdmin' | 'RemoveCollectionAdmin' | 'SetCollectionSponsor' | 'ConfirmSponsorship' | 'RemoveCollectionSponsor' | 'CreateItem' | 'CreateMultipleItems' | 'SetCollectionProperties' | 'DeleteCollectionProperties' | 'SetTokenProperties' | 'DeleteTokenProperties' | 'SetTokenPropertyPermissions' | 'CreateMultipleItemsEx' | 'SetTransfersEnabledFlag' | 'BurnItem' | 'BurnFrom' | 'Transfer' | 'Approve' | 'TransferFrom' | 'SetCollectionLimits' | 'SetCollectionPermissions' | 'Repartition'; } - /** @name UpDataStructsCollectionMode (228) */ + /** @name UpDataStructsCollectionMode (239) */ interface UpDataStructsCollectionMode extends Enum { readonly isNft: boolean; readonly isFungible: boolean; @@ -2273,7 +2517,7 @@ readonly type: 'Nft' | 'Fungible' | 'ReFungible'; } - /** @name UpDataStructsCreateCollectionData (229) */ + /** @name UpDataStructsCreateCollectionData (240) */ interface UpDataStructsCreateCollectionData extends Struct { readonly mode: UpDataStructsCollectionMode; readonly access: Option; @@ -2287,14 +2531,14 @@ readonly properties: Vec; } - /** @name UpDataStructsAccessMode (231) */ + /** @name UpDataStructsAccessMode (242) */ interface UpDataStructsAccessMode extends Enum { readonly isNormal: boolean; readonly isAllowList: boolean; readonly type: 'Normal' | 'AllowList'; } - /** @name UpDataStructsCollectionLimits (233) */ + /** @name UpDataStructsCollectionLimits (244) */ interface UpDataStructsCollectionLimits extends Struct { readonly accountTokenOwnershipLimit: Option; readonly sponsoredDataSize: Option; @@ -2307,7 +2551,7 @@ readonly transfersEnabled: Option; } - /** @name UpDataStructsSponsoringRateLimit (235) */ + /** @name UpDataStructsSponsoringRateLimit (246) */ interface UpDataStructsSponsoringRateLimit extends Enum { readonly isSponsoringDisabled: boolean; readonly isBlocks: boolean; @@ -2315,43 +2559,43 @@ readonly type: 'SponsoringDisabled' | 'Blocks'; } - /** @name UpDataStructsCollectionPermissions (238) */ + /** @name UpDataStructsCollectionPermissions (249) */ interface UpDataStructsCollectionPermissions extends Struct { readonly access: Option; readonly mintMode: Option; readonly nesting: Option; } - /** @name UpDataStructsNestingPermissions (240) */ + /** @name UpDataStructsNestingPermissions (251) */ interface UpDataStructsNestingPermissions extends Struct { readonly tokenOwner: bool; readonly collectionAdmin: bool; readonly restricted: Option; } - /** @name UpDataStructsOwnerRestrictedSet (242) */ + /** @name UpDataStructsOwnerRestrictedSet (253) */ interface UpDataStructsOwnerRestrictedSet extends BTreeSet {} - /** @name UpDataStructsPropertyKeyPermission (247) */ + /** @name UpDataStructsPropertyKeyPermission (258) */ interface UpDataStructsPropertyKeyPermission extends Struct { readonly key: Bytes; readonly permission: UpDataStructsPropertyPermission; } - /** @name UpDataStructsPropertyPermission (248) */ + /** @name UpDataStructsPropertyPermission (259) */ interface UpDataStructsPropertyPermission extends Struct { readonly mutable: bool; readonly collectionAdmin: bool; readonly tokenOwner: bool; } - /** @name UpDataStructsProperty (251) */ + /** @name UpDataStructsProperty (262) */ interface UpDataStructsProperty extends Struct { readonly key: Bytes; readonly value: Bytes; } - /** @name UpDataStructsCreateItemData (254) */ + /** @name UpDataStructsCreateItemData (265) */ interface UpDataStructsCreateItemData extends Enum { readonly isNft: boolean; readonly asNft: UpDataStructsCreateNftData; @@ -2362,23 +2606,23 @@ readonly type: 'Nft' | 'Fungible' | 'ReFungible'; } - /** @name UpDataStructsCreateNftData (255) */ + /** @name UpDataStructsCreateNftData (266) */ interface UpDataStructsCreateNftData extends Struct { readonly properties: Vec; } - /** @name UpDataStructsCreateFungibleData (256) */ + /** @name UpDataStructsCreateFungibleData (267) */ interface UpDataStructsCreateFungibleData extends Struct { readonly value: u128; } - /** @name UpDataStructsCreateReFungibleData (257) */ + /** @name UpDataStructsCreateReFungibleData (268) */ interface UpDataStructsCreateReFungibleData extends Struct { readonly pieces: u128; readonly properties: Vec; } - /** @name UpDataStructsCreateItemExData (260) */ + /** @name UpDataStructsCreateItemExData (271) */ interface UpDataStructsCreateItemExData extends Enum { readonly isNft: boolean; readonly asNft: Vec; @@ -2391,26 +2635,26 @@ readonly type: 'Nft' | 'Fungible' | 'RefungibleMultipleItems' | 'RefungibleMultipleOwners'; } - /** @name UpDataStructsCreateNftExData (262) */ + /** @name UpDataStructsCreateNftExData (273) */ interface UpDataStructsCreateNftExData extends Struct { readonly properties: Vec; readonly owner: PalletEvmAccountBasicCrossAccountIdRepr; } - /** @name UpDataStructsCreateRefungibleExSingleOwner (269) */ + /** @name UpDataStructsCreateRefungibleExSingleOwner (280) */ interface UpDataStructsCreateRefungibleExSingleOwner extends Struct { readonly user: PalletEvmAccountBasicCrossAccountIdRepr; readonly pieces: u128; readonly properties: Vec; } - /** @name UpDataStructsCreateRefungibleExMultipleOwners (271) */ + /** @name UpDataStructsCreateRefungibleExMultipleOwners (282) */ interface UpDataStructsCreateRefungibleExMultipleOwners extends Struct { readonly users: BTreeMap; readonly properties: Vec; } - /** @name PalletUniqueSchedulerCall (272) */ + /** @name PalletUniqueSchedulerCall (283) */ interface PalletUniqueSchedulerCall extends Enum { readonly isScheduleNamed: boolean; readonly asScheduleNamed: { @@ -2435,7 +2679,7 @@ readonly type: 'ScheduleNamed' | 'CancelNamed' | 'ScheduleNamedAfter'; } - /** @name FrameSupportScheduleMaybeHashed (274) */ + /** @name FrameSupportScheduleMaybeHashed (285) */ interface FrameSupportScheduleMaybeHashed extends Enum { readonly isValue: boolean; readonly asValue: Call; @@ -2444,7 +2688,7 @@ readonly type: 'Value' | 'Hash'; } - /** @name PalletConfigurationCall (275) */ + /** @name PalletConfigurationCall (286) */ interface PalletConfigurationCall extends Enum { readonly isSetWeightToFeeCoefficientOverride: boolean; readonly asSetWeightToFeeCoefficientOverride: { @@ -2457,13 +2701,13 @@ readonly type: 'SetWeightToFeeCoefficientOverride' | 'SetMinGasPriceOverride'; } - /** @name PalletTemplateTransactionPaymentCall (276) */ + /** @name PalletTemplateTransactionPaymentCall (287) */ type PalletTemplateTransactionPaymentCall = Null; - /** @name PalletStructureCall (277) */ + /** @name PalletStructureCall (288) */ type PalletStructureCall = Null; - /** @name PalletRmrkCoreCall (278) */ + /** @name PalletRmrkCoreCall (289) */ interface PalletRmrkCoreCall extends Enum { readonly isCreateCollection: boolean; readonly asCreateCollection: { @@ -2569,7 +2813,7 @@ readonly type: 'CreateCollection' | 'DestroyCollection' | 'ChangeCollectionIssuer' | 'LockCollection' | 'MintNft' | 'BurnNft' | 'Send' | 'AcceptNft' | 'RejectNft' | 'AcceptResource' | 'AcceptResourceRemoval' | 'SetProperty' | 'SetPriority' | 'AddBasicResource' | 'AddComposableResource' | 'AddSlotResource' | 'RemoveResource'; } - /** @name RmrkTraitsResourceResourceTypes (284) */ + /** @name RmrkTraitsResourceResourceTypes (295) */ interface RmrkTraitsResourceResourceTypes extends Enum { readonly isBasic: boolean; readonly asBasic: RmrkTraitsResourceBasicResource; @@ -2580,7 +2824,7 @@ readonly type: 'Basic' | 'Composable' | 'Slot'; } - /** @name RmrkTraitsResourceBasicResource (286) */ + /** @name RmrkTraitsResourceBasicResource (297) */ interface RmrkTraitsResourceBasicResource extends Struct { readonly src: Option; readonly metadata: Option; @@ -2588,7 +2832,7 @@ readonly thumb: Option; } - /** @name RmrkTraitsResourceComposableResource (288) */ + /** @name RmrkTraitsResourceComposableResource (299) */ interface RmrkTraitsResourceComposableResource extends Struct { readonly parts: Vec; readonly base: u32; @@ -2598,7 +2842,7 @@ readonly thumb: Option; } - /** @name RmrkTraitsResourceSlotResource (289) */ + /** @name RmrkTraitsResourceSlotResource (300) */ interface RmrkTraitsResourceSlotResource extends Struct { readonly base: u32; readonly src: Option; @@ -2608,7 +2852,7 @@ readonly thumb: Option; } - /** @name PalletRmrkEquipCall (292) */ + /** @name PalletRmrkEquipCall (303) */ interface PalletRmrkEquipCall extends Enum { readonly isCreateBase: boolean; readonly asCreateBase: { @@ -2630,7 +2874,7 @@ readonly type: 'CreateBase' | 'ThemeAdd' | 'Equippable'; } - /** @name RmrkTraitsPartPartType (295) */ + /** @name RmrkTraitsPartPartType (306) */ interface RmrkTraitsPartPartType extends Enum { readonly isFixedPart: boolean; readonly asFixedPart: RmrkTraitsPartFixedPart; @@ -2639,14 +2883,14 @@ readonly type: 'FixedPart' | 'SlotPart'; } - /** @name RmrkTraitsPartFixedPart (297) */ + /** @name RmrkTraitsPartFixedPart (308) */ interface RmrkTraitsPartFixedPart extends Struct { readonly id: u32; readonly z: u32; readonly src: Bytes; } - /** @name RmrkTraitsPartSlotPart (298) */ + /** @name RmrkTraitsPartSlotPart (309) */ interface RmrkTraitsPartSlotPart extends Struct { readonly id: u32; readonly equippable: RmrkTraitsPartEquippableList; @@ -2654,7 +2898,7 @@ readonly z: u32; } - /** @name RmrkTraitsPartEquippableList (299) */ + /** @name RmrkTraitsPartEquippableList (310) */ interface RmrkTraitsPartEquippableList extends Enum { readonly isAll: boolean; readonly isEmpty: boolean; @@ -2663,20 +2907,20 @@ readonly type: 'All' | 'Empty' | 'Custom'; } - /** @name RmrkTraitsTheme (301) */ + /** @name RmrkTraitsTheme (312) */ interface RmrkTraitsTheme extends Struct { readonly name: Bytes; readonly properties: Vec; readonly inherit: bool; } - /** @name RmrkTraitsThemeThemeProperty (303) */ + /** @name RmrkTraitsThemeThemeProperty (314) */ interface RmrkTraitsThemeThemeProperty extends Struct { readonly key: Bytes; readonly value: Bytes; } - /** @name PalletAppPromotionCall (305) */ + /** @name PalletAppPromotionCall (316) */ interface PalletAppPromotionCall extends Enum { readonly isSetAdminAddress: boolean; readonly asSetAdminAddress: { @@ -2710,7 +2954,24 @@ readonly type: 'SetAdminAddress' | 'Stake' | 'Unstake' | 'SponsorCollection' | 'StopSponsoringCollection' | 'SponsorContract' | 'StopSponsoringContract' | 'PayoutStakers'; } - /** @name PalletEvmCall (307) */ + /** @name PalletForeignAssetsModuleCall (318) */ + interface PalletForeignAssetsModuleCall extends Enum { + readonly isRegisterForeignAsset: boolean; + readonly asRegisterForeignAsset: { + readonly owner: AccountId32; + readonly location: XcmVersionedMultiLocation; + readonly metadata: PalletForeignAssetsModuleAssetMetadata; + } & Struct; + readonly isUpdateForeignAsset: boolean; + readonly asUpdateForeignAsset: { + readonly foreignAssetId: u32; + readonly location: XcmVersionedMultiLocation; + readonly metadata: PalletForeignAssetsModuleAssetMetadata; + } & Struct; + readonly type: 'RegisterForeignAsset' | 'UpdateForeignAsset'; + } + + /** @name PalletEvmCall (319) */ interface PalletEvmCall extends Enum { readonly isWithdraw: boolean; readonly asWithdraw: { @@ -2755,7 +3016,7 @@ readonly type: 'Withdraw' | 'Call' | 'Create' | 'Create2'; } - /** @name PalletEthereumCall (311) */ + /** @name PalletEthereumCall (323) */ interface PalletEthereumCall extends Enum { readonly isTransact: boolean; readonly asTransact: { @@ -2764,7 +3025,7 @@ readonly type: 'Transact'; } - /** @name EthereumTransactionTransactionV2 (312) */ + /** @name EthereumTransactionTransactionV2 (324) */ interface EthereumTransactionTransactionV2 extends Enum { readonly isLegacy: boolean; readonly asLegacy: EthereumTransactionLegacyTransaction; @@ -2775,7 +3036,7 @@ readonly type: 'Legacy' | 'Eip2930' | 'Eip1559'; } - /** @name EthereumTransactionLegacyTransaction (313) */ + /** @name EthereumTransactionLegacyTransaction (325) */ interface EthereumTransactionLegacyTransaction extends Struct { readonly nonce: U256; readonly gasPrice: U256; @@ -2786,7 +3047,7 @@ readonly signature: EthereumTransactionTransactionSignature; } - /** @name EthereumTransactionTransactionAction (314) */ + /** @name EthereumTransactionTransactionAction (326) */ interface EthereumTransactionTransactionAction extends Enum { readonly isCall: boolean; readonly asCall: H160; @@ -2794,14 +3055,14 @@ readonly type: 'Call' | 'Create'; } - /** @name EthereumTransactionTransactionSignature (315) */ + /** @name EthereumTransactionTransactionSignature (327) */ interface EthereumTransactionTransactionSignature extends Struct { readonly v: u64; readonly r: H256; readonly s: H256; } - /** @name EthereumTransactionEip2930Transaction (317) */ + /** @name EthereumTransactionEip2930Transaction (329) */ interface EthereumTransactionEip2930Transaction extends Struct { readonly chainId: u64; readonly nonce: U256; @@ -2816,13 +3077,13 @@ readonly s: H256; } - /** @name EthereumTransactionAccessListItem (319) */ + /** @name EthereumTransactionAccessListItem (331) */ interface EthereumTransactionAccessListItem extends Struct { readonly address: H160; readonly storageKeys: Vec; } - /** @name EthereumTransactionEip1559Transaction (320) */ + /** @name EthereumTransactionEip1559Transaction (332) */ interface EthereumTransactionEip1559Transaction extends Struct { readonly chainId: u64; readonly nonce: U256; @@ -2838,7 +3099,7 @@ readonly s: H256; } - /** @name PalletEvmMigrationCall (321) */ + /** @name PalletEvmMigrationCall (333) */ interface PalletEvmMigrationCall extends Enum { readonly isBegin: boolean; readonly asBegin: { @@ -2857,13 +3118,13 @@ readonly type: 'Begin' | 'SetData' | 'Finish'; } - /** @name PalletSudoError (324) */ + /** @name PalletSudoError (336) */ interface PalletSudoError extends Enum { readonly isRequireSudo: boolean; readonly type: 'RequireSudo'; } - /** @name OrmlVestingModuleError (326) */ + /** @name OrmlVestingModuleError (338) */ interface OrmlVestingModuleError extends Enum { readonly isZeroVestingPeriod: boolean; readonly isZeroVestingPeriodCount: boolean; @@ -2874,21 +3135,77 @@ readonly type: 'ZeroVestingPeriod' | 'ZeroVestingPeriodCount' | 'InsufficientBalanceToLock' | 'TooManyVestingSchedules' | 'AmountLow' | 'MaxVestingSchedulesExceeded'; } - /** @name CumulusPalletXcmpQueueInboundChannelDetails (328) */ + /** @name OrmlXtokensModuleError (339) */ + interface OrmlXtokensModuleError extends Enum { + readonly isAssetHasNoReserve: boolean; + readonly isNotCrossChainTransfer: boolean; + readonly isInvalidDest: boolean; + readonly isNotCrossChainTransferableCurrency: boolean; + readonly isUnweighableMessage: boolean; + readonly isXcmExecutionFailed: boolean; + readonly isCannotReanchor: boolean; + readonly isInvalidAncestry: boolean; + readonly isInvalidAsset: boolean; + readonly isDestinationNotInvertible: boolean; + readonly isBadVersion: boolean; + readonly isDistinctReserveForAssetAndFee: boolean; + readonly isZeroFee: boolean; + readonly isZeroAmount: boolean; + readonly isTooManyAssetsBeingSent: boolean; + readonly isAssetIndexNonExistent: boolean; + readonly isFeeNotEnough: boolean; + readonly isNotSupportedMultiLocation: boolean; + readonly isMinXcmFeeNotDefined: boolean; + readonly type: 'AssetHasNoReserve' | 'NotCrossChainTransfer' | 'InvalidDest' | 'NotCrossChainTransferableCurrency' | 'UnweighableMessage' | 'XcmExecutionFailed' | 'CannotReanchor' | 'InvalidAncestry' | 'InvalidAsset' | 'DestinationNotInvertible' | 'BadVersion' | 'DistinctReserveForAssetAndFee' | 'ZeroFee' | 'ZeroAmount' | 'TooManyAssetsBeingSent' | 'AssetIndexNonExistent' | 'FeeNotEnough' | 'NotSupportedMultiLocation' | 'MinXcmFeeNotDefined'; + } + + /** @name OrmlTokensBalanceLock (342) */ + interface OrmlTokensBalanceLock extends Struct { + readonly id: U8aFixed; + readonly amount: u128; + } + + /** @name OrmlTokensAccountData (344) */ + interface OrmlTokensAccountData extends Struct { + readonly free: u128; + readonly reserved: u128; + readonly frozen: u128; + } + + /** @name OrmlTokensReserveData (346) */ + interface OrmlTokensReserveData extends Struct { + readonly id: Null; + readonly amount: u128; + } + + /** @name OrmlTokensModuleError (348) */ + interface OrmlTokensModuleError extends Enum { + readonly isBalanceTooLow: boolean; + readonly isAmountIntoBalanceFailed: boolean; + readonly isLiquidityRestrictions: boolean; + readonly isMaxLocksExceeded: boolean; + readonly isKeepAlive: boolean; + readonly isExistentialDeposit: boolean; + readonly isDeadAccount: boolean; + readonly isTooManyReserves: boolean; + readonly type: 'BalanceTooLow' | 'AmountIntoBalanceFailed' | 'LiquidityRestrictions' | 'MaxLocksExceeded' | 'KeepAlive' | 'ExistentialDeposit' | 'DeadAccount' | 'TooManyReserves'; + } + + /** @name CumulusPalletXcmpQueueInboundChannelDetails (350) */ interface CumulusPalletXcmpQueueInboundChannelDetails extends Struct { readonly sender: u32; readonly state: CumulusPalletXcmpQueueInboundState; readonly messageMetadata: Vec>; } - /** @name CumulusPalletXcmpQueueInboundState (329) */ + /** @name CumulusPalletXcmpQueueInboundState (351) */ interface CumulusPalletXcmpQueueInboundState extends Enum { readonly isOk: boolean; readonly isSuspended: boolean; readonly type: 'Ok' | 'Suspended'; } - /** @name PolkadotParachainPrimitivesXcmpMessageFormat (332) */ + /** @name PolkadotParachainPrimitivesXcmpMessageFormat (354) */ interface PolkadotParachainPrimitivesXcmpMessageFormat extends Enum { readonly isConcatenatedVersionedXcm: boolean; readonly isConcatenatedEncodedBlob: boolean; @@ -2896,7 +3213,7 @@ readonly type: 'ConcatenatedVersionedXcm' | 'ConcatenatedEncodedBlob' | 'Signals'; } - /** @name CumulusPalletXcmpQueueOutboundChannelDetails (335) */ + /** @name CumulusPalletXcmpQueueOutboundChannelDetails (357) */ interface CumulusPalletXcmpQueueOutboundChannelDetails extends Struct { readonly recipient: u32; readonly state: CumulusPalletXcmpQueueOutboundState; @@ -2905,14 +3222,14 @@ readonly lastIndex: u16; } - /** @name CumulusPalletXcmpQueueOutboundState (336) */ + /** @name CumulusPalletXcmpQueueOutboundState (358) */ interface CumulusPalletXcmpQueueOutboundState extends Enum { readonly isOk: boolean; readonly isSuspended: boolean; readonly type: 'Ok' | 'Suspended'; } - /** @name CumulusPalletXcmpQueueQueueConfigData (338) */ + /** @name CumulusPalletXcmpQueueQueueConfigData (360) */ interface CumulusPalletXcmpQueueQueueConfigData extends Struct { readonly suspendThreshold: u32; readonly dropThreshold: u32; @@ -2922,7 +3239,7 @@ readonly xcmpMaxIndividualWeight: u64; } - /** @name CumulusPalletXcmpQueueError (340) */ + /** @name CumulusPalletXcmpQueueError (362) */ interface CumulusPalletXcmpQueueError extends Enum { readonly isFailedToSend: boolean; readonly isBadXcmOrigin: boolean; @@ -2932,7 +3249,7 @@ readonly type: 'FailedToSend' | 'BadXcmOrigin' | 'BadXcm' | 'BadOverweightIndex' | 'WeightOverLimit'; } - /** @name PalletXcmError (341) */ + /** @name PalletXcmError (363) */ interface PalletXcmError extends Enum { readonly isUnreachable: boolean; readonly isSendFailure: boolean; @@ -2950,29 +3267,29 @@ readonly type: 'Unreachable' | 'SendFailure' | 'Filtered' | 'UnweighableMessage' | 'DestinationNotInvertible' | 'Empty' | 'CannotReanchor' | 'TooManyAssets' | 'InvalidOrigin' | 'BadVersion' | 'BadLocation' | 'NoSubscription' | 'AlreadySubscribed'; } - /** @name CumulusPalletXcmError (342) */ + /** @name CumulusPalletXcmError (364) */ type CumulusPalletXcmError = Null; - /** @name CumulusPalletDmpQueueConfigData (343) */ + /** @name CumulusPalletDmpQueueConfigData (365) */ interface CumulusPalletDmpQueueConfigData extends Struct { readonly maxIndividual: u64; } - /** @name CumulusPalletDmpQueuePageIndexData (344) */ + /** @name CumulusPalletDmpQueuePageIndexData (366) */ interface CumulusPalletDmpQueuePageIndexData extends Struct { readonly beginUsed: u32; readonly endUsed: u32; readonly overweightCount: u64; } - /** @name CumulusPalletDmpQueueError (347) */ + /** @name CumulusPalletDmpQueueError (369) */ interface CumulusPalletDmpQueueError extends Enum { readonly isUnknown: boolean; readonly isOverLimit: boolean; readonly type: 'Unknown' | 'OverLimit'; } - /** @name PalletUniqueError (351) */ + /** @name PalletUniqueError (373) */ interface PalletUniqueError extends Enum { readonly isCollectionDecimalPointLimitExceeded: boolean; readonly isConfirmUnsetSponsorFail: boolean; @@ -2981,7 +3298,7 @@ readonly type: 'CollectionDecimalPointLimitExceeded' | 'ConfirmUnsetSponsorFail' | 'EmptyArgument' | 'RepartitionCalledOnNonRefungibleCollection'; } - /** @name PalletUniqueSchedulerScheduledV3 (354) */ + /** @name PalletUniqueSchedulerScheduledV3 (376) */ interface PalletUniqueSchedulerScheduledV3 extends Struct { readonly maybeId: Option; readonly priority: u8; @@ -2990,7 +3307,7 @@ readonly origin: OpalRuntimeOriginCaller; } - /** @name OpalRuntimeOriginCaller (355) */ + /** @name OpalRuntimeOriginCaller (377) */ interface OpalRuntimeOriginCaller extends Enum { readonly isSystem: boolean; readonly asSystem: FrameSupportDispatchRawOrigin; @@ -3004,7 +3321,7 @@ readonly type: 'System' | 'Void' | 'PolkadotXcm' | 'CumulusXcm' | 'Ethereum'; } - /** @name FrameSupportDispatchRawOrigin (356) */ + /** @name FrameSupportDispatchRawOrigin (378) */ interface FrameSupportDispatchRawOrigin extends Enum { readonly isRoot: boolean; readonly isSigned: boolean; @@ -3013,7 +3330,7 @@ readonly type: 'Root' | 'Signed' | 'None'; } - /** @name PalletXcmOrigin (357) */ + /** @name PalletXcmOrigin (379) */ interface PalletXcmOrigin extends Enum { readonly isXcm: boolean; readonly asXcm: XcmV1MultiLocation; @@ -3022,7 +3339,7 @@ readonly type: 'Xcm' | 'Response'; } - /** @name CumulusPalletXcmOrigin (358) */ + /** @name CumulusPalletXcmOrigin (380) */ interface CumulusPalletXcmOrigin extends Enum { readonly isRelay: boolean; readonly isSiblingParachain: boolean; @@ -3030,17 +3347,17 @@ readonly type: 'Relay' | 'SiblingParachain'; } - /** @name PalletEthereumRawOrigin (359) */ + /** @name PalletEthereumRawOrigin (381) */ interface PalletEthereumRawOrigin extends Enum { readonly isEthereumTransaction: boolean; readonly asEthereumTransaction: H160; readonly type: 'EthereumTransaction'; } - /** @name SpCoreVoid (360) */ + /** @name SpCoreVoid (382) */ type SpCoreVoid = Null; - /** @name PalletUniqueSchedulerError (361) */ + /** @name PalletUniqueSchedulerError (383) */ interface PalletUniqueSchedulerError extends Enum { readonly isFailedToSchedule: boolean; readonly isNotFound: boolean; @@ -3049,7 +3366,7 @@ readonly type: 'FailedToSchedule' | 'NotFound' | 'TargetBlockNumberInPast' | 'RescheduleNoChange'; } - /** @name UpDataStructsCollection (362) */ + /** @name UpDataStructsCollection (384) */ interface UpDataStructsCollection extends Struct { readonly owner: AccountId32; readonly mode: UpDataStructsCollectionMode; @@ -3059,10 +3376,10 @@ readonly sponsorship: UpDataStructsSponsorshipStateAccountId32; readonly limits: UpDataStructsCollectionLimits; readonly permissions: UpDataStructsCollectionPermissions; - readonly externalCollection: bool; + readonly flags: U8aFixed; } - /** @name UpDataStructsSponsorshipStateAccountId32 (363) */ + /** @name UpDataStructsSponsorshipStateAccountId32 (385) */ interface UpDataStructsSponsorshipStateAccountId32 extends Enum { readonly isDisabled: boolean; readonly isUnconfirmed: boolean; @@ -3072,43 +3389,43 @@ readonly type: 'Disabled' | 'Unconfirmed' | 'Confirmed'; } - /** @name UpDataStructsProperties (364) */ + /** @name UpDataStructsProperties (387) */ interface UpDataStructsProperties extends Struct { readonly map: UpDataStructsPropertiesMapBoundedVec; readonly consumedSpace: u32; readonly spaceLimit: u32; } - /** @name UpDataStructsPropertiesMapBoundedVec (365) */ + /** @name UpDataStructsPropertiesMapBoundedVec (388) */ interface UpDataStructsPropertiesMapBoundedVec extends BTreeMap {} - /** @name UpDataStructsPropertiesMapPropertyPermission (370) */ + /** @name UpDataStructsPropertiesMapPropertyPermission (393) */ interface UpDataStructsPropertiesMapPropertyPermission extends BTreeMap {} - /** @name UpDataStructsCollectionStats (377) */ + /** @name UpDataStructsCollectionStats (400) */ interface UpDataStructsCollectionStats extends Struct { readonly created: u32; readonly destroyed: u32; readonly alive: u32; } - /** @name UpDataStructsTokenChild (378) */ + /** @name UpDataStructsTokenChild (401) */ interface UpDataStructsTokenChild extends Struct { readonly token: u32; readonly collection: u32; } - /** @name PhantomTypeUpDataStructs (379) */ + /** @name PhantomTypeUpDataStructs (402) */ interface PhantomTypeUpDataStructs extends Vec> {} - /** @name UpDataStructsTokenData (381) */ + /** @name UpDataStructsTokenData (404) */ interface UpDataStructsTokenData extends Struct { readonly properties: Vec; readonly owner: Option; readonly pieces: u128; } - /** @name UpDataStructsRpcCollection (383) */ + /** @name UpDataStructsRpcCollection (406) */ interface UpDataStructsRpcCollection extends Struct { readonly owner: AccountId32; readonly mode: UpDataStructsCollectionMode; @@ -3121,9 +3438,10 @@ readonly tokenPropertyPermissions: Vec; readonly properties: Vec; readonly readOnly: bool; + readonly foreign: bool; } - /** @name RmrkTraitsCollectionCollectionInfo (384) */ + /** @name RmrkTraitsCollectionCollectionInfo (407) */ interface RmrkTraitsCollectionCollectionInfo extends Struct { readonly issuer: AccountId32; readonly metadata: Bytes; @@ -3132,7 +3450,7 @@ readonly nftsCount: u32; } - /** @name RmrkTraitsNftNftInfo (385) */ + /** @name RmrkTraitsNftNftInfo (408) */ interface RmrkTraitsNftNftInfo extends Struct { readonly owner: RmrkTraitsNftAccountIdOrCollectionNftTuple; readonly royalty: Option; @@ -3141,13 +3459,13 @@ readonly pending: bool; } - /** @name RmrkTraitsNftRoyaltyInfo (387) */ + /** @name RmrkTraitsNftRoyaltyInfo (410) */ interface RmrkTraitsNftRoyaltyInfo extends Struct { readonly recipient: AccountId32; readonly amount: Permill; } - /** @name RmrkTraitsResourceResourceInfo (388) */ + /** @name RmrkTraitsResourceResourceInfo (411) */ interface RmrkTraitsResourceResourceInfo extends Struct { readonly id: u32; readonly resource: RmrkTraitsResourceResourceTypes; @@ -3155,26 +3473,26 @@ readonly pendingRemoval: bool; } - /** @name RmrkTraitsPropertyPropertyInfo (389) */ + /** @name RmrkTraitsPropertyPropertyInfo (412) */ interface RmrkTraitsPropertyPropertyInfo extends Struct { readonly key: Bytes; readonly value: Bytes; } - /** @name RmrkTraitsBaseBaseInfo (390) */ + /** @name RmrkTraitsBaseBaseInfo (413) */ interface RmrkTraitsBaseBaseInfo extends Struct { readonly issuer: AccountId32; readonly baseType: Bytes; readonly symbol: Bytes; } - /** @name RmrkTraitsNftNftChild (391) */ + /** @name RmrkTraitsNftNftChild (414) */ interface RmrkTraitsNftNftChild extends Struct { readonly collectionId: u32; readonly nftId: u32; } - /** @name PalletCommonError (393) */ + /** @name PalletCommonError (416) */ interface PalletCommonError extends Enum { readonly isCollectionNotFound: boolean; readonly isMustBeTokenOwner: boolean; @@ -3213,7 +3531,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 (395) */ + /** @name PalletFungibleError (418) */ interface PalletFungibleError extends Enum { readonly isNotFungibleDataUsedToMintFungibleCollectionToken: boolean; readonly isFungibleItemsHaveNoId: boolean; @@ -3223,12 +3541,12 @@ readonly type: 'NotFungibleDataUsedToMintFungibleCollectionToken' | 'FungibleItemsHaveNoId' | 'FungibleItemsDontHaveData' | 'FungibleDisallowsNesting' | 'SettingPropertiesNotAllowed'; } - /** @name PalletRefungibleItemData (396) */ + /** @name PalletRefungibleItemData (419) */ interface PalletRefungibleItemData extends Struct { readonly constData: Bytes; } - /** @name PalletRefungibleError (401) */ + /** @name PalletRefungibleError (424) */ interface PalletRefungibleError extends Enum { readonly isNotRefungibleDataUsedToMintFungibleCollectionToken: boolean; readonly isWrongRefungiblePieces: boolean; @@ -3238,19 +3556,19 @@ readonly type: 'NotRefungibleDataUsedToMintFungibleCollectionToken' | 'WrongRefungiblePieces' | 'RepartitionWhileNotOwningAllPieces' | 'RefungibleDisallowsNesting' | 'SettingPropertiesNotAllowed'; } - /** @name PalletNonfungibleItemData (402) */ + /** @name PalletNonfungibleItemData (425) */ interface PalletNonfungibleItemData extends Struct { readonly owner: PalletEvmAccountBasicCrossAccountIdRepr; } - /** @name UpDataStructsPropertyScope (404) */ + /** @name UpDataStructsPropertyScope (427) */ interface UpDataStructsPropertyScope extends Enum { readonly isNone: boolean; readonly isRmrk: boolean; readonly type: 'None' | 'Rmrk'; } - /** @name PalletNonfungibleError (406) */ + /** @name PalletNonfungibleError (429) */ interface PalletNonfungibleError extends Enum { readonly isNotNonfungibleDataUsedToMintFungibleCollectionToken: boolean; readonly isNonfungibleItemsHaveNoAmount: boolean; @@ -3258,7 +3576,7 @@ readonly type: 'NotNonfungibleDataUsedToMintFungibleCollectionToken' | 'NonfungibleItemsHaveNoAmount' | 'CantBurnNftWithChildren'; } - /** @name PalletStructureError (407) */ + /** @name PalletStructureError (430) */ interface PalletStructureError extends Enum { readonly isOuroborosDetected: boolean; readonly isDepthLimit: boolean; @@ -3267,7 +3585,7 @@ readonly type: 'OuroborosDetected' | 'DepthLimit' | 'BreadthLimit' | 'TokenNotFound'; } - /** @name PalletRmrkCoreError (408) */ + /** @name PalletRmrkCoreError (431) */ interface PalletRmrkCoreError extends Enum { readonly isCorruptedCollectionType: boolean; readonly isRmrkPropertyKeyIsTooLong: boolean; @@ -3291,7 +3609,7 @@ readonly type: 'CorruptedCollectionType' | 'RmrkPropertyKeyIsTooLong' | 'RmrkPropertyValueIsTooLong' | 'RmrkPropertyIsNotFound' | 'UnableToDecodeRmrkData' | 'CollectionNotEmpty' | 'NoAvailableCollectionId' | 'NoAvailableNftId' | 'CollectionUnknown' | 'NoPermission' | 'NonTransferable' | 'CollectionFullOrLocked' | 'ResourceDoesntExist' | 'CannotSendToDescendentOrSelf' | 'CannotAcceptNonOwnedNft' | 'CannotRejectNonOwnedNft' | 'CannotRejectNonPendingNft' | 'ResourceNotPending' | 'NoAvailableResourceId'; } - /** @name PalletRmrkEquipError (410) */ + /** @name PalletRmrkEquipError (433) */ interface PalletRmrkEquipError extends Enum { readonly isPermissionError: boolean; readonly isNoAvailableBaseId: boolean; @@ -3303,7 +3621,7 @@ readonly type: 'PermissionError' | 'NoAvailableBaseId' | 'NoAvailablePartId' | 'BaseDoesntExist' | 'NeedsDefaultThemeFirst' | 'PartDoesntExist' | 'NoEquippableOnFixedPart'; } - /** @name PalletAppPromotionError (416) */ + /** @name PalletAppPromotionError (439) */ interface PalletAppPromotionError extends Enum { readonly isAdminNotSet: boolean; readonly isNoPermission: boolean; @@ -3314,7 +3632,16 @@ readonly type: 'AdminNotSet' | 'NoPermission' | 'NotSufficientFunds' | 'PendingForBlockOverflow' | 'SponsorNotSet' | 'IncorrectLockedBalanceOperation'; } - /** @name PalletEvmError (419) */ + /** @name PalletForeignAssetsModuleError (440) */ + interface PalletForeignAssetsModuleError extends Enum { + readonly isBadLocation: boolean; + readonly isMultiLocationExisted: boolean; + readonly isAssetIdNotExists: boolean; + readonly isAssetIdExisted: boolean; + readonly type: 'BadLocation' | 'MultiLocationExisted' | 'AssetIdNotExists' | 'AssetIdExisted'; + } + + /** @name PalletEvmError (443) */ interface PalletEvmError extends Enum { readonly isBalanceLow: boolean; readonly isFeeOverflow: boolean; @@ -3325,7 +3652,7 @@ readonly type: 'BalanceLow' | 'FeeOverflow' | 'PaymentOverflow' | 'WithdrawFailed' | 'GasPriceTooLow' | 'InvalidNonce'; } - /** @name FpRpcTransactionStatus (422) */ + /** @name FpRpcTransactionStatus (446) */ interface FpRpcTransactionStatus extends Struct { readonly transactionHash: H256; readonly transactionIndex: u32; @@ -3336,10 +3663,10 @@ readonly logsBloom: EthbloomBloom; } - /** @name EthbloomBloom (424) */ + /** @name EthbloomBloom (448) */ interface EthbloomBloom extends U8aFixed {} - /** @name EthereumReceiptReceiptV3 (426) */ + /** @name EthereumReceiptReceiptV3 (450) */ interface EthereumReceiptReceiptV3 extends Enum { readonly isLegacy: boolean; readonly asLegacy: EthereumReceiptEip658ReceiptData; @@ -3350,7 +3677,7 @@ readonly type: 'Legacy' | 'Eip2930' | 'Eip1559'; } - /** @name EthereumReceiptEip658ReceiptData (427) */ + /** @name EthereumReceiptEip658ReceiptData (451) */ interface EthereumReceiptEip658ReceiptData extends Struct { readonly statusCode: u8; readonly usedGas: U256; @@ -3358,14 +3685,14 @@ readonly logs: Vec; } - /** @name EthereumBlock (428) */ + /** @name EthereumBlock (452) */ interface EthereumBlock extends Struct { readonly header: EthereumHeader; readonly transactions: Vec; readonly ommers: Vec; } - /** @name EthereumHeader (429) */ + /** @name EthereumHeader (453) */ interface EthereumHeader extends Struct { readonly parentHash: H256; readonly ommersHash: H256; @@ -3384,24 +3711,24 @@ readonly nonce: EthereumTypesHashH64; } - /** @name EthereumTypesHashH64 (430) */ + /** @name EthereumTypesHashH64 (454) */ interface EthereumTypesHashH64 extends U8aFixed {} - /** @name PalletEthereumError (435) */ + /** @name PalletEthereumError (459) */ interface PalletEthereumError extends Enum { readonly isInvalidSignature: boolean; readonly isPreLogExists: boolean; readonly type: 'InvalidSignature' | 'PreLogExists'; } - /** @name PalletEvmCoderSubstrateError (436) */ + /** @name PalletEvmCoderSubstrateError (460) */ interface PalletEvmCoderSubstrateError extends Enum { readonly isOutOfGas: boolean; readonly isOutOfFund: boolean; readonly type: 'OutOfGas' | 'OutOfFund'; } - /** @name UpDataStructsSponsorshipStateBasicCrossAccountIdRepr (437) */ + /** @name UpDataStructsSponsorshipStateBasicCrossAccountIdRepr (461) */ interface UpDataStructsSponsorshipStateBasicCrossAccountIdRepr extends Enum { readonly isDisabled: boolean; readonly isUnconfirmed: boolean; @@ -3411,7 +3738,7 @@ readonly type: 'Disabled' | 'Unconfirmed' | 'Confirmed'; } - /** @name PalletEvmContractHelpersSponsoringModeT (438) */ + /** @name PalletEvmContractHelpersSponsoringModeT (462) */ interface PalletEvmContractHelpersSponsoringModeT extends Enum { readonly isDisabled: boolean; readonly isAllowlisted: boolean; @@ -3419,21 +3746,22 @@ readonly type: 'Disabled' | 'Allowlisted' | 'Generous'; } - /** @name PalletEvmContractHelpersError (440) */ + /** @name PalletEvmContractHelpersError (468) */ interface PalletEvmContractHelpersError extends Enum { readonly isNoPermission: boolean; readonly isNoPendingSponsor: boolean; - readonly type: 'NoPermission' | 'NoPendingSponsor'; + readonly isTooManyMethodsHaveSponsoredLimit: boolean; + readonly type: 'NoPermission' | 'NoPendingSponsor' | 'TooManyMethodsHaveSponsoredLimit'; } - /** @name PalletEvmMigrationError (441) */ + /** @name PalletEvmMigrationError (469) */ interface PalletEvmMigrationError extends Enum { readonly isAccountNotEmpty: boolean; readonly isAccountIsNotMigrating: boolean; readonly type: 'AccountNotEmpty' | 'AccountIsNotMigrating'; } - /** @name SpRuntimeMultiSignature (443) */ + /** @name SpRuntimeMultiSignature (471) */ interface SpRuntimeMultiSignature extends Enum { readonly isEd25519: boolean; readonly asEd25519: SpCoreEd25519Signature; @@ -3444,34 +3772,34 @@ readonly type: 'Ed25519' | 'Sr25519' | 'Ecdsa'; } - /** @name SpCoreEd25519Signature (444) */ + /** @name SpCoreEd25519Signature (472) */ interface SpCoreEd25519Signature extends U8aFixed {} - /** @name SpCoreSr25519Signature (446) */ + /** @name SpCoreSr25519Signature (474) */ interface SpCoreSr25519Signature extends U8aFixed {} - /** @name SpCoreEcdsaSignature (447) */ + /** @name SpCoreEcdsaSignature (475) */ interface SpCoreEcdsaSignature extends U8aFixed {} - /** @name FrameSystemExtensionsCheckSpecVersion (450) */ + /** @name FrameSystemExtensionsCheckSpecVersion (478) */ type FrameSystemExtensionsCheckSpecVersion = Null; - /** @name FrameSystemExtensionsCheckGenesis (451) */ + /** @name FrameSystemExtensionsCheckGenesis (479) */ type FrameSystemExtensionsCheckGenesis = Null; - /** @name FrameSystemExtensionsCheckNonce (454) */ + /** @name FrameSystemExtensionsCheckNonce (482) */ interface FrameSystemExtensionsCheckNonce extends Compact {} - /** @name FrameSystemExtensionsCheckWeight (455) */ + /** @name FrameSystemExtensionsCheckWeight (483) */ type FrameSystemExtensionsCheckWeight = Null; - /** @name PalletTemplateTransactionPaymentChargeTransactionPayment (456) */ + /** @name PalletTemplateTransactionPaymentChargeTransactionPayment (484) */ interface PalletTemplateTransactionPaymentChargeTransactionPayment extends Compact {} - /** @name OpalRuntimeRuntime (457) */ + /** @name OpalRuntimeRuntime (485) */ type OpalRuntimeRuntime = Null; - /** @name PalletEthereumFakeTransactionFinalizer (458) */ + /** @name PalletEthereumFakeTransactionFinalizer (486) */ type PalletEthereumFakeTransactionFinalizer = Null; } // declare module --- a/tests/src/pallet-presence.test.ts +++ b/tests/src/pallet-presence.test.ts @@ -45,6 +45,8 @@ 'nonfungible', 'charging', 'configuration', + 'tokens', + 'xtokens', ]; // Pallets that depend on consensus and governance configuration @@ -61,11 +63,18 @@ const refungible = 'refungible'; const scheduler = 'scheduler'; + const foreignAssets = 'foreignassets'; const rmrkPallets = ['rmrkcore', 'rmrkequip']; const appPromotion = 'apppromotion'; if (chain.eq('OPAL by UNIQUE')) { - requiredPallets.push(refungible, scheduler, appPromotion, ...rmrkPallets); + requiredPallets.push( + refungible, + scheduler, + foreignAssets, + appPromotion, + ...rmrkPallets, + ); } else if (chain.eq('QUARTZ by UNIQUE')) { requiredPallets.push(refungible); } else if (chain.eq('UNIQUE')) { --- a/tests/src/substrate/substrate-api.ts +++ b/tests/src/substrate/substrate-api.ts @@ -110,6 +110,9 @@ if (status.isBroadcast) { return TransactionStatus.NotReady; } + if (status.isRetracted) { + return TransactionStatus.NotReady; + } if (status.isInBlock || status.isFinalized) { if(events.filter(e => e.event.data.method === 'ExtrinsicFailed').length > 0) { return TransactionStatus.Fail; @@ -148,18 +151,32 @@ }); } +/** + * @deprecated use `executeTransaction` instead + */ export function submitTransactionAsync(sender: IKeyringPair, transaction: SubmittableExtrinsic): Promise { /* eslint no-async-promise-executor: "off" */ return new Promise(async (resolve, reject) => { try { - await transaction.signAndSend(sender, ({events = [], status}) => { + await transaction.signAndSend(sender, ({events = [], status, dispatchError}) => { const transactionStatus = getTransactionStatus(events, status); if (transactionStatus === TransactionStatus.Success) { resolve(events); } else if (transactionStatus === TransactionStatus.Fail) { - console.log(`Something went wrong with transaction. Status: ${status}`); + let moduleError = null; + + if (dispatchError) { + if (dispatchError.isModule) { + const modErr = dispatchError.asModule; + const errorMeta = dispatchError.registry.findMetaError(modErr); + + moduleError = JSON.stringify(errorMeta, null, 4); + } + } + + console.log(`Something went wrong with transaction. Status: ${status}\nModule error: ${moduleError}`); reject(events); } }); --- a/tests/src/util/helpers.ts +++ b/tests/src/util/helpers.ts @@ -16,7 +16,7 @@ import '../interfaces/augment-api-rpc'; import '../interfaces/augment-api-query'; -import {ApiPromise} from '@polkadot/api'; +import {ApiPromise, Keyring} from '@polkadot/api'; import type {AccountId, EventRecord, Event, BlockNumber} from '@polkadot/types/interfaces'; import type {GenericEventData} from '@polkadot/types'; import {AnyTuple, IEvent, IKeyringPair} from '@polkadot/types/types'; @@ -63,14 +63,14 @@ export async function isQuartz(): Promise { 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') + if (typeof modulesNames === 'undefined') modulesNames = api.runtimeMetadata.asLatest.pallets.map(m => m.name.toString().toLowerCase()); return modulesNames; } @@ -105,6 +105,19 @@ return api.registry.createType('AccountId', '0x' + number.toString(16).padStart(64, '0')).toJSON(); } +export function bigIntToDecimals(number: bigint, decimals = 18): string { + const numberStr = number.toString(); + const dotPos = numberStr.length - decimals; + + if (dotPos <= 0) { + return '0.' + '0'.repeat(Math.abs(dotPos)) + numberStr; + } else { + const intPart = numberStr.substring(0, dotPos); + const fractPart = numberStr.substring(dotPos); + return intPart + '.' + fractPart; + } +} + export function normalizeAccountId(input: string | AccountId | CrossAccountId | IKeyringPair): CrossAccountId { if (typeof input === 'string') { if (input.length >= 47) { @@ -291,7 +304,7 @@ export function getCreateItemsResult(events: EventRecord[]): CreateItemResult[] { const results: CreateItemResult[] = []; - + const genericResult = getGenericResult(events, 'common', 'ItemCreated', (data) => { const collectionId = parseInt(data[0].toString(), 10); const itemId = parseInt(data[1].toString(), 10); @@ -316,15 +329,15 @@ export function getCreateItemResult(events: EventRecord[]): CreateItemResult { const genericResult = getGenericResult(events, 'common', 'ItemCreated', (data) => data.map(function(value) { return value.toJSON(); })); - - if (genericResult.data == null) + + if (genericResult.data == null) return { success: genericResult.success, collectionId: 0, itemId: 0, amount: 0, }; - else + else return { success: genericResult.success, collectionId: genericResult.data[0] as number, @@ -336,7 +349,7 @@ export function getDestroyItemsResult(events: EventRecord[]): DestroyItemResult[] { const results: DestroyItemResult[] = []; - + const genericResult = getGenericResult(events, 'common', 'ItemDestroyed', (data) => { const collectionId = parseInt(data[0].toString(), 10); const itemId = parseInt(data[1].toString(), 10); @@ -1102,6 +1115,19 @@ return balance; } +export async function paraSiblingSovereignAccount(paraid: number): Promise { + return usingApi(async api => { + // We are getting a *sibling* parachain sovereign account, + // so we need a sibling prefix: encoded(b"sibl") == 0x7369626c + const siblingPrefix = '0x7369626c'; + + const encodedParaId = api.createType('u32', paraid).toHex(true).substring(2); + const suffix = '000000000000000000000000000000000000000000000000'; + + return siblingPrefix + encodedParaId + suffix; + }); +} + export async function transferBalanceTo(api: ApiPromise, source: IKeyringPair, target: string, amount = 1000n * UNIQUE) { const tx = api.tx.balances.transfer(target, amount); const events = await submitTransactionAsync(source, tx); @@ -1125,9 +1151,9 @@ expect(blockNumber).to.be.greaterThan(0); const scheduleTx = api.tx.scheduler.scheduleNamed( // schedule scheduledId, - expectedBlockNumber, - repetitions > 1 ? [period, repetitions] : null, - 0, + expectedBlockNumber, + repetitions > 1 ? [period, repetitions] : null, + 0, {Value: operationTx as any}, ); @@ -1152,13 +1178,13 @@ expect(blockNumber).to.be.greaterThan(0); const scheduleTx = api.tx.scheduler.scheduleNamed( // schedule scheduledId, - expectedBlockNumber, - repetitions <= 1 ? null : [period, repetitions], - 0, + expectedBlockNumber, + repetitions <= 1 ? null : [period, repetitions], + 0, {Value: operationTx as any}, ); - //const events = + //const events = await expect(submitTransactionExpectFailAsync(sender, scheduleTx)).to.be.rejected; //expect(getGenericResult(events).success).to.be.false; }); @@ -1222,7 +1248,7 @@ const transferTx = api.tx.balances.transfer(recipient.address, amount); const balanceBefore = await getFreeBalance(recipient); - + await scheduleExpectSuccess(transferTx, sender, blockSchedule, scheduledId, period, repetitions); expect(await getFreeBalance(recipient)).to.be.equal(balanceBefore); @@ -1738,6 +1764,12 @@ return (await api.rpc.unique.collectionById(collectionId)).unwrap(); } +export const describe_xcm = ( + process.env.RUN_XCM_TESTS + ? describe + : describe.skip +); + export async function waitNewBlocks(blocksCount = 1): Promise { await usingApi(async (api) => { const promise = new Promise(async (resolve) => { @@ -1754,6 +1786,45 @@ }); } +export async function waitEvent( + api: ApiPromise, + maxBlocksToWait: number, + eventSection: string, + eventMethod: string, +): Promise { + + const promise = new Promise(async (resolve) => { + const unsubscribe = await api.rpc.chain.subscribeNewHeads(async header => { + const blockNumber = header.number.toHuman(); + const blockHash = header.hash; + const eventIdStr = `${eventSection}.${eventMethod}`; + const waitLimitStr = `wait blocks remaining: ${maxBlocksToWait}`; + + console.log(`[Block #${blockNumber}] Waiting for event \`${eventIdStr}\` (${waitLimitStr})`); + + const apiAt = await api.at(blockHash); + const eventRecords = await apiAt.query.system.events(); + + const neededEvent = eventRecords.find(r => { + return r.event.section == eventSection && r.event.method == eventMethod; + }); + + if (neededEvent) { + unsubscribe(); + resolve(neededEvent); + } else if (maxBlocksToWait > 0) { + maxBlocksToWait--; + } else { + console.log(`Event \`${eventIdStr}\` is NOT found`); + + unsubscribe(); + resolve(null); + } + }); + }); + return promise; +} + export async function repartitionRFT( api: ApiPromise, collectionId: number, @@ -1782,6 +1853,11 @@ itApi.only = (name: string, cb: (apis: { api: ApiPromise, privateKeyWrapper: (account: string) => IKeyringPair }) => any) => itApi(name, cb, {only: true}); itApi.skip = (name: string, cb: (apis: { api: ApiPromise, privateKeyWrapper: (account: string) => IKeyringPair }) => any) => itApi(name, cb, {skip: true}); +let accountSeed = 10000; +export function generateKeyringPair(keyring: Keyring) { + const privateKey = `0xDEADBEEF${(Date.now() + (accountSeed++)).toString(16).padStart(64 - 8, '0')}`; + return keyring.addFromUri(privateKey); +} export async function expectSubstrateEventsAtBlock(api: ApiPromise, blockNumber: AnyNumber | BlockNumber, section: string, methods: string[], dryRun = false) { const blockHash = await api.rpc.chain.getBlockHash(blockNumber); @@ -1800,4 +1876,4 @@ expect(subEvents).to.be.like(events); } return subEvents; -} \ No newline at end of file +} --- /dev/null +++ b/tests/src/xcm/xcmOpal.test.ts @@ -0,0 +1,527 @@ +// 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 . + +import chai from 'chai'; +import chaiAsPromised from 'chai-as-promised'; + +import {WsProvider} from '@polkadot/api'; +import {ApiOptions} from '@polkadot/api/types'; +import {IKeyringPair} from '@polkadot/types/types'; +import usingApi, {executeTransaction} from './../substrate/substrate-api'; +import {bigIntToDecimals, describe_xcm, getGenericResult, paraSiblingSovereignAccount} from './../util/helpers'; +import waitNewBlocks from './../substrate/wait-new-blocks'; +import {normalizeAccountId} from './../util/helpers'; +import getBalance from './../substrate/get-balance'; + + +chai.use(chaiAsPromised); +const expect = chai.expect; + +const STATEMINE_CHAIN = 1000; +const UNIQUE_CHAIN = 2095; + +const RELAY_PORT = '9844'; +const UNIQUE_PORT = '9944'; +const STATEMINE_PORT = '9948'; +const STATEMINE_PALLET_INSTANCE = 50; +const ASSET_ID = 100; +const ASSET_METADATA_DECIMALS = 18; +const ASSET_METADATA_NAME = 'USDT'; +const ASSET_METADATA_DESCRIPTION = 'USDT'; +const ASSET_METADATA_MINIMAL_BALANCE = 1; + +const WESTMINT_DECIMALS = 12; + +const TRANSFER_AMOUNT = 1_000_000_000_000_000_000n; + +// 10,000.00 (ten thousands) USDT +const ASSET_AMOUNT = 1_000_000_000_000_000_000_000n; + +describe_xcm('[XCM] Integration test: Exchanging USDT with Westmint', () => { + let alice: IKeyringPair; + let bob: IKeyringPair; + + let balanceStmnBefore: bigint; + let balanceStmnAfter: bigint; + + let balanceOpalBefore: bigint; + let balanceOpalAfter: bigint; + let balanceOpalFinal: bigint; + + let balanceBobBefore: bigint; + let balanceBobAfter: bigint; + let balanceBobFinal: bigint; + + let balanceBobRelayTokenBefore: bigint; + let balanceBobRelayTokenAfter: bigint; + + + before(async () => { + await usingApi(async (api, privateKeyWrapper) => { + alice = privateKeyWrapper('//Alice'); + bob = privateKeyWrapper('//Bob'); // funds donor + }); + + const statemineApiOptions: ApiOptions = { + provider: new WsProvider('ws://127.0.0.1:' + STATEMINE_PORT), + }; + + const uniqueApiOptions: ApiOptions = { + provider: new WsProvider('ws://127.0.0.1:' + UNIQUE_PORT), + }; + + const relayApiOptions: ApiOptions = { + provider: new WsProvider('ws://127.0.0.1:' + RELAY_PORT), + }; + + await usingApi(async (api) => { + + // 350.00 (three hundred fifty) DOT + const fundingAmount = 3_500_000_000_000; + + const tx = api.tx.assets.create(ASSET_ID, alice.addressRaw, ASSET_METADATA_MINIMAL_BALANCE); + const events = await executeTransaction(api, alice, tx); + const result = getGenericResult(events); + expect(result.success).to.be.true; + + // set metadata + const tx2 = api.tx.assets.setMetadata(ASSET_ID, ASSET_METADATA_NAME, ASSET_METADATA_DESCRIPTION, ASSET_METADATA_DECIMALS); + const events2 = await executeTransaction(api, alice, tx2); + const result2 = getGenericResult(events2); + expect(result2.success).to.be.true; + + // mint some amount of asset + const tx3 = api.tx.assets.mint(ASSET_ID, alice.addressRaw, ASSET_AMOUNT); + const events3 = await executeTransaction(api, alice, tx3); + const result3 = getGenericResult(events3); + expect(result3.success).to.be.true; + + // funding parachain sovereing account (Parachain: 2095) + const parachainSovereingAccount = await paraSiblingSovereignAccount(UNIQUE_CHAIN); + const tx4 = api.tx.balances.transfer(parachainSovereingAccount, fundingAmount); + const events4 = await executeTransaction(api, bob, tx4); + const result4 = getGenericResult(events4); + expect(result4.success).to.be.true; + + }, statemineApiOptions); + + + await usingApi(async (api) => { + + const location = { + V1: { + parents: 1, + interior: {X3: [ + { + Parachain: STATEMINE_CHAIN, + }, + { + PalletInstance: STATEMINE_PALLET_INSTANCE, + }, + { + GeneralIndex: ASSET_ID, + }, + ]}, + }, + }; + + const metadata = + { + name: ASSET_ID, + symbol: ASSET_METADATA_NAME, + decimals: ASSET_METADATA_DECIMALS, + minimalBalance: ASSET_METADATA_MINIMAL_BALANCE, + }; + //registerForeignAsset(owner, location, metadata) + const tx = api.tx.foreignAssets.registerForeignAsset(alice.addressRaw, location, metadata); + const sudoTx = api.tx.sudo.sudo(tx as any); + const events = await executeTransaction(api, alice, sudoTx); + const result = getGenericResult(events); + expect(result.success).to.be.true; + + [balanceOpalBefore] = await getBalance(api, [alice.address]); + + }, uniqueApiOptions); + + + // Providing the relay currency to the unique sender account + await usingApi(async (api) => { + const destination = { + V1: { + parents: 0, + interior: {X1: { + Parachain: UNIQUE_CHAIN, + }, + }, + }}; + + const beneficiary = { + V1: { + parents: 0, + interior: {X1: { + AccountId32: { + network: 'Any', + id: alice.addressRaw, + }, + }}, + }, + }; + + const assets = { + V1: [ + { + id: { + Concrete: { + parents: 0, + interior: 'Here', + }, + }, + fun: { + Fungible: 50_000_000_000_000_000n, + }, + }, + ], + }; + + const feeAssetItem = 0; + + const weightLimit = { + Limited: 5_000_000_000, + }; + + const tx = api.tx.xcmPallet.limitedReserveTransferAssets(destination, beneficiary, assets, feeAssetItem, weightLimit); + const events = await executeTransaction(api, alice, tx); + const result = getGenericResult(events); + expect(result.success).to.be.true; + }, relayApiOptions); + + }); + + it('Should connect and send USDT from Westmint to Opal', async () => { + + const statemineApiOptions: ApiOptions = { + provider: new WsProvider('ws://127.0.0.1:' + STATEMINE_PORT), + }; + + const uniqueApiOptions: ApiOptions = { + provider: new WsProvider('ws://127.0.0.1:' + UNIQUE_PORT), + }; + + await usingApi(async (api) => { + + const dest = { + V1: { + parents: 1, + interior: {X1: { + Parachain: UNIQUE_CHAIN, + }, + }, + }}; + + const beneficiary = { + V1: { + parents: 0, + interior: {X1: { + AccountId32: { + network: 'Any', + id: alice.addressRaw, + }, + }}, + }, + }; + + const assets = { + V1: [ + { + id: { + Concrete: { + parents: 0, + interior: { + X2: [ + { + PalletInstance: STATEMINE_PALLET_INSTANCE, + }, + { + GeneralIndex: ASSET_ID, + }, + ]}, + }, + }, + fun: { + Fungible: TRANSFER_AMOUNT, + }, + }, + ], + }; + + const feeAssetItem = 0; + + const weightLimit = { + Limited: 5000000000, + }; + + [balanceStmnBefore] = await getBalance(api, [alice.address]); + + const tx = api.tx.polkadotXcm.limitedReserveTransferAssets(dest, beneficiary, assets, feeAssetItem, weightLimit); + const events = await executeTransaction(api, alice, tx); + const result = getGenericResult(events); + expect(result.success).to.be.true; + + [balanceStmnAfter] = await getBalance(api, [alice.address]); + + // common good parachain take commission in it native token + console.log( + 'Opal to Westmint transaction fees on Westmint: %s WND', + bigIntToDecimals(balanceStmnBefore - balanceStmnAfter, WESTMINT_DECIMALS), + ); + expect(balanceStmnBefore > balanceStmnAfter).to.be.true; + + }, statemineApiOptions); + + + // ensure that asset has been delivered + await usingApi(async (api) => { + await waitNewBlocks(api, 3); + // expext collection id will be with id 1 + const free = (await api.query.fungible.balance(1, normalizeAccountId(alice.address))).toBigInt(); + + [balanceOpalAfter] = await getBalance(api, [alice.address]); + + // commission has not paid in USDT token + expect(free == TRANSFER_AMOUNT).to.be.true; + console.log( + 'Opal to Westmint transaction fees on Opal: %s USDT', + bigIntToDecimals(TRANSFER_AMOUNT - free), + ); + // ... and parachain native token + expect(balanceOpalAfter == balanceOpalBefore).to.be.true; + console.log( + 'Opal to Westmint transaction fees on Opal: %s WND', + bigIntToDecimals(balanceOpalAfter - balanceOpalBefore, WESTMINT_DECIMALS), + ); + + }, uniqueApiOptions); + + }); + + it('Should connect and send USDT from Unique to Statemine back', async () => { + + const uniqueApiOptions: ApiOptions = { + provider: new WsProvider('ws://127.0.0.1:' + UNIQUE_PORT), + }; + + const statemineApiOptions: ApiOptions = { + provider: new WsProvider('ws://127.0.0.1:' + STATEMINE_PORT), + }; + + await usingApi(async (api) => { + const destination = { + V1: { + parents: 1, + interior: {X2: [ + { + Parachain: STATEMINE_CHAIN, + }, + { + AccountId32: { + network: 'Any', + id: alice.addressRaw, + }, + }, + ]}, + }, + }; + + const currencies: [any, bigint][] = [ + [ + { + ForeignAssetId: 0, + }, + //10_000_000_000_000_000n, + TRANSFER_AMOUNT, + ], + [ + { + NativeAssetId: 'Parent', + }, + 400_000_000_000_000n, + ], + ]; + + const feeItem = 1; + const destWeight = 500000000000; + + const tx = api.tx.xTokens.transferMulticurrencies(currencies, feeItem, destination, destWeight); + const events = await executeTransaction(api, alice, tx); + const result = getGenericResult(events); + expect(result.success).to.be.true; + + // the commission has been paid in parachain native token + [balanceOpalFinal] = await getBalance(api, [alice.address]); + expect(balanceOpalAfter > balanceOpalFinal).to.be.true; + }, uniqueApiOptions); + + await usingApi(async (api) => { + await waitNewBlocks(api, 3); + + // The USDT token never paid fees. Its amount not changed from begin value. + // Also check that xcm transfer has been succeeded + const free = ((await api.query.assets.account(100, alice.address)).toHuman()) as any; + expect(BigInt(free.balance.replace(/,/g, '')) == ASSET_AMOUNT).to.be.true; + }, statemineApiOptions); + }); + + it('Should connect and send Relay token to Unique', async () => { + + const uniqueApiOptions: ApiOptions = { + provider: new WsProvider('ws://127.0.0.1:' + UNIQUE_PORT), + }; + + const uniqueApiOptions2: ApiOptions = { + provider: new WsProvider('ws://127.0.0.1:' + UNIQUE_PORT), + }; + + const relayApiOptions: ApiOptions = { + provider: new WsProvider('ws://127.0.0.1:' + RELAY_PORT), + }; + + const TRANSFER_AMOUNT_RELAY = 50_000_000_000_000_000n; + + await usingApi(async (api) => { + [balanceBobBefore] = await getBalance(api, [bob.address]); + balanceBobRelayTokenBefore = BigInt(((await api.query.tokens.accounts(bob.addressRaw, {NativeAssetId: 'Parent'})).toJSON() as any).free); + + }, uniqueApiOptions); + + // Providing the relay currency to the unique sender account + await usingApi(async (api) => { + const destination = { + V1: { + parents: 0, + interior: {X1: { + Parachain: UNIQUE_CHAIN, + }, + }, + }}; + + const beneficiary = { + V1: { + parents: 0, + interior: {X1: { + AccountId32: { + network: 'Any', + id: bob.addressRaw, + }, + }}, + }, + }; + + const assets = { + V1: [ + { + id: { + Concrete: { + parents: 0, + interior: 'Here', + }, + }, + fun: { + Fungible: TRANSFER_AMOUNT_RELAY, + }, + }, + ], + }; + + const feeAssetItem = 0; + + const weightLimit = { + Limited: 5_000_000_000, + }; + + const tx = api.tx.xcmPallet.limitedReserveTransferAssets(destination, beneficiary, assets, feeAssetItem, weightLimit); + const events = await executeTransaction(api, bob, tx); + const result = getGenericResult(events); + expect(result.success).to.be.true; + }, relayApiOptions); + + + await usingApi(async (api) => { + await waitNewBlocks(api, 3); + + [balanceBobAfter] = await getBalance(api, [bob.address]); + balanceBobRelayTokenAfter = BigInt(((await api.query.tokens.accounts(bob.addressRaw, {NativeAssetId: 'Parent'})).toJSON() as any).free); + const wndFee = balanceBobRelayTokenAfter - TRANSFER_AMOUNT_RELAY - balanceBobRelayTokenBefore; + console.log( + 'Relay (Westend) to Opal transaction fees: %s OPL', + bigIntToDecimals(balanceBobAfter - balanceBobBefore), + ); + console.log( + 'Relay (Westend) to Opal transaction fees: %s WND', + bigIntToDecimals(wndFee, WESTMINT_DECIMALS), + ); + expect(balanceBobBefore == balanceBobAfter).to.be.true; + expect(balanceBobRelayTokenBefore < balanceBobRelayTokenAfter).to.be.true; + }, uniqueApiOptions2); + + }); + + it('Should connect and send Relay token back', async () => { + const uniqueApiOptions: ApiOptions = { + provider: new WsProvider('ws://127.0.0.1:' + UNIQUE_PORT), + }; + + await usingApi(async (api) => { + const destination = { + V1: { + parents: 1, + interior: {X2: [ + { + Parachain: STATEMINE_CHAIN, + }, + { + AccountId32: { + network: 'Any', + id: bob.addressRaw, + }, + }, + ]}, + }, + }; + + const currencies: any = [ + [ + { + NativeAssetId: 'Parent', + }, + 50_000_000_000_000_000n, + ], + ]; + + const feeItem = 0; + const destWeight = 500000000000; + + const tx = api.tx.xTokens.transferMulticurrencies(currencies, feeItem, destination, destWeight); + const events = await executeTransaction(api, bob, tx); + const result = getGenericResult(events); + expect(result.success).to.be.true; + + [balanceBobFinal] = await getBalance(api, [bob.address]); + console.log('Relay (Westend) to Opal transaction fees: %s OPL', balanceBobAfter - balanceBobFinal); + + }, uniqueApiOptions); + }); + +}); --- /dev/null +++ b/tests/src/xcm/xcmQuartz.test.ts @@ -0,0 +1,799 @@ +// 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 . + +import chai from 'chai'; +import chaiAsPromised from 'chai-as-promised'; + +import {WsProvider, Keyring} from '@polkadot/api'; +import {ApiOptions} from '@polkadot/api/types'; +import {IKeyringPair} from '@polkadot/types/types'; +import usingApi, {submitTransactionAsync} from '../substrate/substrate-api'; +import {getGenericResult, generateKeyringPair, waitEvent, describe_xcm, bigIntToDecimals} from '../util/helpers'; +import {MultiLocation} from '@polkadot/types/interfaces'; +import {blake2AsHex} from '@polkadot/util-crypto'; +import waitNewBlocks from '../substrate/wait-new-blocks'; +import getBalance from '../substrate/get-balance'; +import {XcmV2TraitsOutcome, XcmV2TraitsError} from '../interfaces'; + +chai.use(chaiAsPromised); +const expect = chai.expect; + +const QUARTZ_CHAIN = 2095; +const KARURA_CHAIN = 2000; +const MOONRIVER_CHAIN = 2023; + +const RELAY_PORT = 9844; +const KARURA_PORT = 9946; +const MOONRIVER_PORT = 9947; + +const KARURA_DECIMALS = 12; + +const TRANSFER_AMOUNT = 2000000000000000000000000n; + +function parachainApiOptions(port: number): ApiOptions { + return { + provider: new WsProvider('ws://127.0.0.1:' + port.toString()), + }; +} + +function karuraOptions(): ApiOptions { + return parachainApiOptions(KARURA_PORT); +} + +function moonriverOptions(): ApiOptions { + return parachainApiOptions(MOONRIVER_PORT); +} + +function relayOptions(): ApiOptions { + return parachainApiOptions(RELAY_PORT); +} + +describe_xcm('[XCM] Integration test: Exchanging tokens with Karura', () => { + let alice: IKeyringPair; + let randomAccount: IKeyringPair; + + let balanceQuartzTokenInit: bigint; + let balanceQuartzTokenMiddle: bigint; + let balanceQuartzTokenFinal: bigint; + let balanceKaruraTokenInit: bigint; + let balanceKaruraTokenMiddle: bigint; + let balanceKaruraTokenFinal: bigint; + let balanceQuartzForeignTokenInit: bigint; + let balanceQuartzForeignTokenMiddle: bigint; + let balanceQuartzForeignTokenFinal: bigint; + + before(async () => { + await usingApi(async (api, privateKeyWrapper) => { + const keyringSr25519 = new Keyring({type: 'sr25519'}); + + alice = privateKeyWrapper('//Alice'); + randomAccount = generateKeyringPair(keyringSr25519); + }); + + // Karura side + await usingApi( + async (api) => { + const destination = { + V0: { + X2: [ + 'Parent', + { + Parachain: QUARTZ_CHAIN, + }, + ], + }, + }; + + const metadata = { + name: 'QTZ', + symbol: 'QTZ', + decimals: 18, + minimalBalance: 1, + }; + + const tx = api.tx.assetRegistry.registerForeignAsset(destination, metadata); + const sudoTx = api.tx.sudo.sudo(tx as any); + const events = await submitTransactionAsync(alice, sudoTx); + const result = getGenericResult(events); + expect(result.success).to.be.true; + + const tx1 = api.tx.balances.transfer(randomAccount.address, 10000000000000n); + const events1 = await submitTransactionAsync(alice, tx1); + const result1 = getGenericResult(events1); + expect(result1.success).to.be.true; + + [balanceKaruraTokenInit] = await getBalance(api, [randomAccount.address]); + { + const {free} = (await api.query.tokens.accounts(randomAccount.addressRaw, {ForeignAsset: 0})).toJSON() as any; + balanceQuartzForeignTokenInit = BigInt(free); + } + }, + karuraOptions(), + ); + + // Quartz side + await usingApi(async (api) => { + const tx0 = api.tx.balances.transfer(randomAccount.address, 10n * TRANSFER_AMOUNT); + const events0 = await submitTransactionAsync(alice, tx0); + const result0 = getGenericResult(events0); + expect(result0.success).to.be.true; + + [balanceQuartzTokenInit] = await getBalance(api, [randomAccount.address]); + }); + }); + + it('Should connect and send QTZ to Karura', async () => { + + // Quartz side + await usingApi(async (api) => { + + const destination = { + V0: { + X2: [ + 'Parent', + { + Parachain: KARURA_CHAIN, + }, + ], + }, + }; + + const beneficiary = { + V0: { + X1: { + AccountId32: { + network: 'Any', + id: randomAccount.addressRaw, + }, + }, + }, + }; + + const assets = { + V1: [ + { + id: { + Concrete: { + parents: 0, + interior: 'Here', + }, + }, + fun: { + Fungible: TRANSFER_AMOUNT, + }, + }, + ], + }; + + const feeAssetItem = 0; + + const weightLimit = { + Limited: 5000000000, + }; + + const tx = api.tx.polkadotXcm.limitedReserveTransferAssets(destination, beneficiary, assets, feeAssetItem, weightLimit); + const events = await submitTransactionAsync(randomAccount, tx); + const result = getGenericResult(events); + expect(result.success).to.be.true; + + [balanceQuartzTokenMiddle] = await getBalance(api, [randomAccount.address]); + + const qtzFees = balanceQuartzTokenInit - balanceQuartzTokenMiddle - TRANSFER_AMOUNT; + console.log('[Quartz -> Karura] transaction fees on Quartz: %s QTZ', bigIntToDecimals(qtzFees)); + expect(qtzFees > 0n).to.be.true; + }); + + // Karura side + await usingApi( + async (api) => { + await waitNewBlocks(api, 3); + const {free} = (await api.query.tokens.accounts(randomAccount.addressRaw, {ForeignAsset: 0})).toJSON() as any; + balanceQuartzForeignTokenMiddle = BigInt(free); + + [balanceKaruraTokenMiddle] = await getBalance(api, [randomAccount.address]); + + const karFees = balanceKaruraTokenInit - balanceKaruraTokenMiddle; + const qtzIncomeTransfer = balanceQuartzForeignTokenMiddle - balanceQuartzForeignTokenInit; + + console.log( + '[Quartz -> Karura] transaction fees on Karura: %s KAR', + bigIntToDecimals(karFees, KARURA_DECIMALS), + ); + console.log('[Quartz -> Karura] income %s QTZ', bigIntToDecimals(qtzIncomeTransfer)); + expect(karFees == 0n).to.be.true; + expect(qtzIncomeTransfer == TRANSFER_AMOUNT).to.be.true; + }, + karuraOptions(), + ); + }); + + it('Should connect to Karura and send QTZ back', async () => { + + // Karura side + await usingApi( + async (api) => { + const destination = { + V1: { + parents: 1, + interior: { + X2: [ + {Parachain: QUARTZ_CHAIN}, + { + AccountId32: { + network: 'Any', + id: randomAccount.addressRaw, + }, + }, + ], + }, + }, + }; + + const id = { + ForeignAsset: 0, + }; + + const destWeight = 50000000; + + const tx = api.tx.xTokens.transfer(id as any, TRANSFER_AMOUNT, destination, destWeight); + const events = await submitTransactionAsync(randomAccount, tx); + const result = getGenericResult(events); + expect(result.success).to.be.true; + + [balanceKaruraTokenFinal] = await getBalance(api, [randomAccount.address]); + { + const {free} = (await api.query.tokens.accounts(randomAccount.addressRaw, id)).toJSON() as any; + balanceQuartzForeignTokenFinal = BigInt(free); + } + + const karFees = balanceKaruraTokenMiddle - balanceKaruraTokenFinal; + const qtzOutcomeTransfer = balanceQuartzForeignTokenMiddle - balanceQuartzForeignTokenFinal; + + console.log( + '[Karura -> Quartz] transaction fees on Karura: %s KAR', + bigIntToDecimals(karFees, KARURA_DECIMALS), + ); + console.log('[Karura -> Quartz] outcome %s QTZ', bigIntToDecimals(qtzOutcomeTransfer)); + + expect(karFees > 0).to.be.true; + expect(qtzOutcomeTransfer == TRANSFER_AMOUNT).to.be.true; + }, + karuraOptions(), + ); + + // Quartz side + await usingApi(async (api) => { + await waitNewBlocks(api, 3); + + [balanceQuartzTokenFinal] = await getBalance(api, [randomAccount.address]); + const actuallyDelivered = balanceQuartzTokenFinal - balanceQuartzTokenMiddle; + expect(actuallyDelivered > 0).to.be.true; + + console.log('[Karura -> Quartz] actually delivered %s QTZ', bigIntToDecimals(actuallyDelivered)); + + const qtzFees = TRANSFER_AMOUNT - actuallyDelivered; + console.log('[Karura -> Quartz] transaction fees on Quartz: %s QTZ', bigIntToDecimals(qtzFees)); + expect(qtzFees == 0n).to.be.true; + }); + }); +}); + +// These tests are relevant only when the foreign asset pallet is disabled +describe_xcm('[XCM] Integration test: Quartz rejects non-native tokens', () => { + let alice: IKeyringPair; + + before(async () => { + await usingApi(async (api, privateKeyWrapper) => { + alice = privateKeyWrapper('//Alice'); + }); + }); + + it('Quartz rejects tokens from the Relay', async () => { + await usingApi(async (api) => { + const destination = { + V1: { + parents: 0, + interior: {X1: { + Parachain: QUARTZ_CHAIN, + }, + }, + }}; + + const beneficiary = { + V1: { + parents: 0, + interior: {X1: { + AccountId32: { + network: 'Any', + id: alice.addressRaw, + }, + }}, + }, + }; + + const assets = { + V1: [ + { + id: { + Concrete: { + parents: 0, + interior: 'Here', + }, + }, + fun: { + Fungible: 50_000_000_000_000_000n, + }, + }, + ], + }; + + const feeAssetItem = 0; + + const weightLimit = { + Limited: 5_000_000_000, + }; + + const tx = api.tx.xcmPallet.limitedReserveTransferAssets(destination, beneficiary, assets, feeAssetItem, weightLimit); + const events = await submitTransactionAsync(alice, tx); + const result = getGenericResult(events); + expect(result.success).to.be.true; + }, relayOptions()); + + await usingApi(async api => { + const maxWaitBlocks = 3; + const dmpQueueExecutedDownward = await waitEvent( + api, + maxWaitBlocks, + 'dmpQueue', + 'ExecutedDownward', + ); + + expect( + dmpQueueExecutedDownward != null, + '[Relay] dmpQueue.ExecutedDownward event is expected', + ).to.be.true; + + const event = dmpQueueExecutedDownward!.event; + const outcome = event.data[1] as XcmV2TraitsOutcome; + + expect( + outcome.isIncomplete, + '[Relay] The outcome of the XCM should be `Incomplete`', + ).to.be.true; + + const incomplete = outcome.asIncomplete; + expect( + incomplete[1].toString() == 'AssetNotFound', + '[Relay] The XCM error should be `AssetNotFound`', + ).to.be.true; + }); + }); + + it('Quartz rejects KAR tokens from Karura', async () => { + await usingApi(async (api) => { + const destination = { + V1: { + parents: 1, + interior: { + X2: [ + {Parachain: QUARTZ_CHAIN}, + { + AccountId32: { + network: 'Any', + id: alice.addressRaw, + }, + }, + ], + }, + }, + }; + + const id = { + Token: 'KAR', + }; + + const destWeight = 50000000; + + const tx = api.tx.xTokens.transfer(id as any, 100_000_000_000, destination, destWeight); + const events = await submitTransactionAsync(alice, tx); + const result = getGenericResult(events); + expect(result.success).to.be.true; + }, karuraOptions()); + + await usingApi(async api => { + const maxWaitBlocks = 3; + const xcmpQueueFailEvent = await waitEvent(api, maxWaitBlocks, 'xcmpQueue', 'Fail'); + + expect( + xcmpQueueFailEvent != null, + '[Karura] xcmpQueue.FailEvent event is expected', + ).to.be.true; + + const event = xcmpQueueFailEvent!.event; + const outcome = event.data[1] as XcmV2TraitsError; + + expect( + outcome.isUntrustedReserveLocation, + '[Karura] The XCM error should be `UntrustedReserveLocation`', + ).to.be.true; + }); + }); +}); + +describe_xcm('[XCM] Integration test: Exchanging QTZ with Moonriver', () => { + + // Quartz constants + let quartzAlice: IKeyringPair; + let quartzAssetLocation; + + let randomAccountQuartz: IKeyringPair; + let randomAccountMoonriver: IKeyringPair; + + // Moonriver constants + let assetId: string; + + const moonriverKeyring = new Keyring({type: 'ethereum'}); + const alithPrivateKey = '0x5fb92d6e98884f76de468fa3f6278f8807c48bebc13595d45af5bdc4da702133'; + const baltatharPrivateKey = '0x8075991ce870b93a8870eca0c0f91913d12f47948ca0fd25b49c6fa7cdbeee8b'; + const dorothyPrivateKey = '0x39539ab1876910bbf3a223d84a29e28f1cb4e2e456503e7e91ed39b2e7223d68'; + + const alithAccount = moonriverKeyring.addFromUri(alithPrivateKey, undefined, 'ethereum'); + const baltatharAccount = moonriverKeyring.addFromUri(baltatharPrivateKey, undefined, 'ethereum'); + const dorothyAccount = moonriverKeyring.addFromUri(dorothyPrivateKey, undefined, 'ethereum'); + + const councilVotingThreshold = 2; + const technicalCommitteeThreshold = 2; + const votingPeriod = 3; + const delayPeriod = 0; + + const quartzAssetMetadata = { + name: 'xcQuartz', + symbol: 'xcQTZ', + decimals: 18, + isFrozen: false, + minimalBalance: 1, + }; + + let balanceQuartzTokenInit: bigint; + let balanceQuartzTokenMiddle: bigint; + let balanceQuartzTokenFinal: bigint; + let balanceForeignQtzTokenInit: bigint; + let balanceForeignQtzTokenMiddle: bigint; + let balanceForeignQtzTokenFinal: bigint; + let balanceMovrTokenInit: bigint; + let balanceMovrTokenMiddle: bigint; + let balanceMovrTokenFinal: bigint; + + before(async () => { + await usingApi(async (api, privateKeyWrapper) => { + const keyringEth = new Keyring({type: 'ethereum'}); + const keyringSr25519 = new Keyring({type: 'sr25519'}); + + quartzAlice = privateKeyWrapper('//Alice'); + randomAccountQuartz = generateKeyringPair(keyringSr25519); + randomAccountMoonriver = generateKeyringPair(keyringEth); + + balanceForeignQtzTokenInit = 0n; + }); + + await usingApi( + async (api) => { + + // >>> Sponsoring Dorothy >>> + console.log('Sponsoring Dorothy.......'); + const tx0 = api.tx.balances.transfer(dorothyAccount.address, 11_000_000_000_000_000_000n); + const events0 = await submitTransactionAsync(alithAccount, tx0); + const result0 = getGenericResult(events0); + expect(result0.success).to.be.true; + console.log('Sponsoring Dorothy.......DONE'); + // <<< Sponsoring Dorothy <<< + + const sourceLocation: MultiLocation = api.createType( + 'MultiLocation', + { + parents: 1, + interior: {X1: {Parachain: QUARTZ_CHAIN}}, + }, + ); + + quartzAssetLocation = {XCM: sourceLocation}; + const existentialDeposit = 1; + const isSufficient = true; + const unitsPerSecond = '1'; + const numAssetsWeightHint = 0; + + const registerTx = api.tx.assetManager.registerForeignAsset( + quartzAssetLocation, + quartzAssetMetadata, + existentialDeposit, + isSufficient, + ); + console.log('Encoded proposal for registerAsset is %s', registerTx.method.toHex() || ''); + + const setUnitsTx = api.tx.assetManager.setAssetUnitsPerSecond( + quartzAssetLocation, + unitsPerSecond, + numAssetsWeightHint, + ); + console.log('Encoded proposal for setAssetUnitsPerSecond is %s', setUnitsTx.method.toHex() || ''); + + const batchCall = api.tx.utility.batchAll([registerTx, setUnitsTx]); + console.log('Encoded proposal for batchCall is %s', batchCall.method.toHex() || ''); + + // >>> Note motion preimage >>> + console.log('Note motion preimage.......'); + const encodedProposal = batchCall?.method.toHex() || ''; + const proposalHash = blake2AsHex(encodedProposal); + console.log('Encoded proposal for batch utility after schedule is %s', encodedProposal); + console.log('Encoded proposal hash for batch utility after schedule is %s', proposalHash); + console.log('Encoded length %d', encodedProposal.length); + + const tx1 = api.tx.democracy.notePreimage(encodedProposal); + const events1 = await submitTransactionAsync(baltatharAccount, tx1); + const result1 = getGenericResult(events1); + expect(result1.success).to.be.true; + console.log('Note motion preimage.......DONE'); + // <<< Note motion preimage <<< + + // >>> Propose external motion through council >>> + console.log('Propose external motion through council.......'); + const externalMotion = api.tx.democracy.externalProposeMajority(proposalHash); + const tx2 = api.tx.councilCollective.propose( + councilVotingThreshold, + externalMotion, + externalMotion.encodedLength, + ); + const events2 = await submitTransactionAsync(baltatharAccount, tx2); + const result2 = getGenericResult(events2); + expect(result2.success).to.be.true; + + const encodedMotion = externalMotion?.method.toHex() || ''; + const motionHash = blake2AsHex(encodedMotion); + console.log('Motion hash is %s', motionHash); + + const tx3 = api.tx.councilCollective.vote(motionHash, 0, true); + { + const events3 = await submitTransactionAsync(dorothyAccount, tx3); + const result3 = getGenericResult(events3); + expect(result3.success).to.be.true; + } + { + const events3 = await submitTransactionAsync(baltatharAccount, tx3); + const result3 = getGenericResult(events3); + expect(result3.success).to.be.true; + } + + const tx4 = api.tx.councilCollective.close(motionHash, 0, 1_000_000_000, externalMotion.encodedLength); + const events4 = await submitTransactionAsync(dorothyAccount, tx4); + const result4 = getGenericResult(events4); + expect(result4.success).to.be.true; + console.log('Propose external motion through council.......DONE'); + // <<< Propose external motion through council <<< + + // >>> Fast track proposal through technical committee >>> + console.log('Fast track proposal through technical committee.......'); + const fastTrack = api.tx.democracy.fastTrack(proposalHash, votingPeriod, delayPeriod); + const tx5 = api.tx.techCommitteeCollective.propose( + technicalCommitteeThreshold, + fastTrack, + fastTrack.encodedLength, + ); + const events5 = await submitTransactionAsync(alithAccount, tx5); + const result5 = getGenericResult(events5); + expect(result5.success).to.be.true; + + const encodedFastTrack = fastTrack?.method.toHex() || ''; + const fastTrackHash = blake2AsHex(encodedFastTrack); + console.log('FastTrack hash is %s', fastTrackHash); + + const proposalIdx = Number(await api.query.techCommitteeCollective.proposalCount()) - 1; + const tx6 = api.tx.techCommitteeCollective.vote(fastTrackHash, proposalIdx, true); + { + const events6 = await submitTransactionAsync(baltatharAccount, tx6); + const result6 = getGenericResult(events6); + expect(result6.success).to.be.true; + } + { + const events6 = await submitTransactionAsync(alithAccount, tx6); + const result6 = getGenericResult(events6); + expect(result6.success).to.be.true; + } + + const tx7 = api.tx.techCommitteeCollective + .close(fastTrackHash, proposalIdx, 1_000_000_000, fastTrack.encodedLength); + const events7 = await submitTransactionAsync(baltatharAccount, tx7); + const result7 = getGenericResult(events7); + expect(result7.success).to.be.true; + console.log('Fast track proposal through technical committee.......DONE'); + // <<< Fast track proposal through technical committee <<< + + // >>> Referendum voting >>> + console.log('Referendum voting.......'); + const tx8 = api.tx.democracy.vote( + 0, + {Standard: {balance: 10_000_000_000_000_000_000n, vote: {aye: true, conviction: 1}}}, + ); + const events8 = await submitTransactionAsync(dorothyAccount, tx8); + const result8 = getGenericResult(events8); + expect(result8.success).to.be.true; + console.log('Referendum voting.......DONE'); + // <<< Referendum voting <<< + + // >>> Acquire Quartz AssetId Info on Moonriver >>> + console.log('Acquire Quartz AssetId Info on Moonriver.......'); + + // Wait for the democracy execute + await waitNewBlocks(api, 5); + + assetId = (await api.query.assetManager.assetTypeId({ + XCM: sourceLocation, + })).toString(); + + console.log('QTZ asset ID is %s', assetId); + console.log('Acquire Quartz AssetId Info on Moonriver.......DONE'); + // >>> Acquire Quartz AssetId Info on Moonriver >>> + + // >>> Sponsoring random Account >>> + console.log('Sponsoring random Account.......'); + const tx10 = api.tx.balances.transfer(randomAccountMoonriver.address, 11_000_000_000_000_000_000n); + const events10 = await submitTransactionAsync(baltatharAccount, tx10); + const result10 = getGenericResult(events10); + expect(result10.success).to.be.true; + console.log('Sponsoring random Account.......DONE'); + // <<< Sponsoring random Account <<< + + [balanceMovrTokenInit] = await getBalance(api, [randomAccountMoonriver.address]); + }, + moonriverOptions(), + ); + + await usingApi(async (api) => { + const tx0 = api.tx.balances.transfer(randomAccountQuartz.address, 10n * TRANSFER_AMOUNT); + const events0 = await submitTransactionAsync(quartzAlice, tx0); + const result0 = getGenericResult(events0); + expect(result0.success).to.be.true; + + [balanceQuartzTokenInit] = await getBalance(api, [randomAccountQuartz.address]); + }); + }); + + it('Should connect and send QTZ to Moonriver', async () => { + await usingApi(async (api) => { + const currencyId = { + NativeAssetId: 'Here', + }; + const dest = { + V1: { + parents: 1, + interior: { + X2: [ + {Parachain: MOONRIVER_CHAIN}, + {AccountKey20: {network: 'Any', key: randomAccountMoonriver.address}}, + ], + }, + }, + }; + const amount = TRANSFER_AMOUNT; + const destWeight = 850000000; + + const tx = api.tx.xTokens.transfer(currencyId, amount, dest, destWeight); + const events = await submitTransactionAsync(randomAccountQuartz, tx); + const result = getGenericResult(events); + expect(result.success).to.be.true; + + [balanceQuartzTokenMiddle] = await getBalance(api, [randomAccountQuartz.address]); + expect(balanceQuartzTokenMiddle < balanceQuartzTokenInit).to.be.true; + + const transactionFees = balanceQuartzTokenInit - balanceQuartzTokenMiddle - TRANSFER_AMOUNT; + console.log('[Quartz -> Moonriver] transaction fees on Quartz: %s QTZ', bigIntToDecimals(transactionFees)); + expect(transactionFees > 0).to.be.true; + }); + + await usingApi( + async (api) => { + await waitNewBlocks(api, 3); + + [balanceMovrTokenMiddle] = await getBalance(api, [randomAccountMoonriver.address]); + + const movrFees = balanceMovrTokenInit - balanceMovrTokenMiddle; + console.log('[Quartz -> Moonriver] transaction fees on Moonriver: %s MOVR',bigIntToDecimals(movrFees)); + expect(movrFees == 0n).to.be.true; + + const qtzRandomAccountAsset = ( + await api.query.assets.account(assetId, randomAccountMoonriver.address) + ).toJSON()! as any; + + balanceForeignQtzTokenMiddle = BigInt(qtzRandomAccountAsset['balance']); + const qtzIncomeTransfer = balanceForeignQtzTokenMiddle - balanceForeignQtzTokenInit; + console.log('[Quartz -> Moonriver] income %s QTZ', bigIntToDecimals(qtzIncomeTransfer)); + expect(qtzIncomeTransfer == TRANSFER_AMOUNT).to.be.true; + }, + moonriverOptions(), + ); + }); + + it('Should connect to Moonriver and send QTZ back', async () => { + await usingApi( + async (api) => { + const asset = { + V1: { + id: { + Concrete: { + parents: 1, + interior: { + X1: {Parachain: QUARTZ_CHAIN}, + }, + }, + }, + fun: { + Fungible: TRANSFER_AMOUNT, + }, + }, + }; + const destination = { + V1: { + parents: 1, + interior: { + X2: [ + {Parachain: QUARTZ_CHAIN}, + {AccountId32: {network: 'Any', id: randomAccountQuartz.addressRaw}}, + ], + }, + }, + }; + const destWeight = 50000000; + + const tx = api.tx.xTokens.transferMultiasset(asset, destination, destWeight); + const events = await submitTransactionAsync(randomAccountMoonriver, tx); + const result = getGenericResult(events); + expect(result.success).to.be.true; + + [balanceMovrTokenFinal] = await getBalance(api, [randomAccountMoonriver.address]); + + const movrFees = balanceMovrTokenMiddle - balanceMovrTokenFinal; + console.log('[Moonriver -> Quartz] transaction fees on Moonriver: %s MOVR', bigIntToDecimals(movrFees)); + expect(movrFees > 0).to.be.true; + + const qtzRandomAccountAsset = ( + await api.query.assets.account(assetId, randomAccountMoonriver.address) + ).toJSON()! as any; + + expect(qtzRandomAccountAsset).to.be.null; + + balanceForeignQtzTokenFinal = 0n; + + const qtzOutcomeTransfer = balanceForeignQtzTokenMiddle - balanceForeignQtzTokenFinal; + console.log('[Quartz -> Moonriver] outcome %s QTZ', bigIntToDecimals(qtzOutcomeTransfer)); + expect(qtzOutcomeTransfer == TRANSFER_AMOUNT).to.be.true; + }, + moonriverOptions(), + ); + + await usingApi(async (api) => { + await waitNewBlocks(api, 3); + + [balanceQuartzTokenFinal] = await getBalance(api, [randomAccountQuartz.address]); + const actuallyDelivered = balanceQuartzTokenFinal - balanceQuartzTokenMiddle; + expect(actuallyDelivered > 0).to.be.true; + + console.log('[Moonriver -> Quartz] actually delivered %s QTZ', bigIntToDecimals(actuallyDelivered)); + + const qtzFees = TRANSFER_AMOUNT - actuallyDelivered; + console.log('[Moonriver -> Quartz] transaction fees on Quartz: %s QTZ', bigIntToDecimals(qtzFees)); + expect(qtzFees == 0n).to.be.true; + }); + }); +}); --- /dev/null +++ b/tests/src/xcm/xcmUnique.test.ts @@ -0,0 +1,799 @@ +// 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 . + +import chai from 'chai'; +import chaiAsPromised from 'chai-as-promised'; + +import {WsProvider, Keyring} from '@polkadot/api'; +import {ApiOptions} from '@polkadot/api/types'; +import {IKeyringPair} from '@polkadot/types/types'; +import usingApi, {submitTransactionAsync} from '../substrate/substrate-api'; +import {getGenericResult, generateKeyringPair, waitEvent, describe_xcm, bigIntToDecimals} from '../util/helpers'; +import {MultiLocation} from '@polkadot/types/interfaces'; +import {blake2AsHex} from '@polkadot/util-crypto'; +import waitNewBlocks from '../substrate/wait-new-blocks'; +import getBalance from '../substrate/get-balance'; +import {XcmV2TraitsError, XcmV2TraitsOutcome} from '../interfaces'; + +chai.use(chaiAsPromised); +const expect = chai.expect; + +const UNIQUE_CHAIN = 2037; +const ACALA_CHAIN = 2000; +const MOONBEAM_CHAIN = 2004; + +const RELAY_PORT = 9844; +const ACALA_PORT = 9946; +const MOONBEAM_PORT = 9947; + +const ACALA_DECIMALS = 12; + +const TRANSFER_AMOUNT = 2000000000000000000000000n; + +function parachainApiOptions(port: number): ApiOptions { + return { + provider: new WsProvider('ws://127.0.0.1:' + port.toString()), + }; +} + +function acalaOptions(): ApiOptions { + return parachainApiOptions(ACALA_PORT); +} + +function moonbeamOptions(): ApiOptions { + return parachainApiOptions(MOONBEAM_PORT); +} + +function relayOptions(): ApiOptions { + return parachainApiOptions(RELAY_PORT); +} + +describe_xcm('[XCM] Integration test: Exchanging tokens with Acala', () => { + let alice: IKeyringPair; + let randomAccount: IKeyringPair; + + let balanceUniqueTokenInit: bigint; + let balanceUniqueTokenMiddle: bigint; + let balanceUniqueTokenFinal: bigint; + let balanceAcalaTokenInit: bigint; + let balanceAcalaTokenMiddle: bigint; + let balanceAcalaTokenFinal: bigint; + let balanceUniqueForeignTokenInit: bigint; + let balanceUniqueForeignTokenMiddle: bigint; + let balanceUniqueForeignTokenFinal: bigint; + + before(async () => { + await usingApi(async (api, privateKeyWrapper) => { + const keyringSr25519 = new Keyring({type: 'sr25519'}); + + alice = privateKeyWrapper('//Alice'); + randomAccount = generateKeyringPair(keyringSr25519); + }); + + // Acala side + await usingApi( + async (api) => { + const destination = { + V0: { + X2: [ + 'Parent', + { + Parachain: UNIQUE_CHAIN, + }, + ], + }, + }; + + const metadata = { + name: 'UNQ', + symbol: 'UNQ', + decimals: 18, + minimalBalance: 1, + }; + + const tx = api.tx.assetRegistry.registerForeignAsset(destination, metadata); + const sudoTx = api.tx.sudo.sudo(tx as any); + const events = await submitTransactionAsync(alice, sudoTx); + const result = getGenericResult(events); + expect(result.success).to.be.true; + + const tx1 = api.tx.balances.transfer(randomAccount.address, 10000000000000n); + const events1 = await submitTransactionAsync(alice, tx1); + const result1 = getGenericResult(events1); + expect(result1.success).to.be.true; + + [balanceAcalaTokenInit] = await getBalance(api, [randomAccount.address]); + { + const {free} = (await api.query.tokens.accounts(randomAccount.addressRaw, {ForeignAsset: 0})).toJSON() as any; + balanceUniqueForeignTokenInit = BigInt(free); + } + }, + acalaOptions(), + ); + + // Unique side + await usingApi(async (api) => { + const tx0 = api.tx.balances.transfer(randomAccount.address, 10n * TRANSFER_AMOUNT); + const events0 = await submitTransactionAsync(alice, tx0); + const result0 = getGenericResult(events0); + expect(result0.success).to.be.true; + + [balanceUniqueTokenInit] = await getBalance(api, [randomAccount.address]); + }); + }); + + it('Should connect and send UNQ to Acala', async () => { + + // Unique side + await usingApi(async (api) => { + + const destination = { + V0: { + X2: [ + 'Parent', + { + Parachain: ACALA_CHAIN, + }, + ], + }, + }; + + const beneficiary = { + V0: { + X1: { + AccountId32: { + network: 'Any', + id: randomAccount.addressRaw, + }, + }, + }, + }; + + const assets = { + V1: [ + { + id: { + Concrete: { + parents: 0, + interior: 'Here', + }, + }, + fun: { + Fungible: TRANSFER_AMOUNT, + }, + }, + ], + }; + + const feeAssetItem = 0; + + const weightLimit = { + Limited: 5000000000, + }; + + const tx = api.tx.polkadotXcm.limitedReserveTransferAssets(destination, beneficiary, assets, feeAssetItem, weightLimit); + const events = await submitTransactionAsync(randomAccount, tx); + const result = getGenericResult(events); + expect(result.success).to.be.true; + + [balanceUniqueTokenMiddle] = await getBalance(api, [randomAccount.address]); + + const unqFees = balanceUniqueTokenInit - balanceUniqueTokenMiddle - TRANSFER_AMOUNT; + console.log('[Unique -> Acala] transaction fees on Unique: %s UNQ', bigIntToDecimals(unqFees)); + expect(unqFees > 0n).to.be.true; + }); + + // Acala side + await usingApi( + async (api) => { + await waitNewBlocks(api, 3); + const {free} = (await api.query.tokens.accounts(randomAccount.addressRaw, {ForeignAsset: 0})).toJSON() as any; + balanceUniqueForeignTokenMiddle = BigInt(free); + + [balanceAcalaTokenMiddle] = await getBalance(api, [randomAccount.address]); + + const acaFees = balanceAcalaTokenInit - balanceAcalaTokenMiddle; + const unqIncomeTransfer = balanceUniqueForeignTokenMiddle - balanceUniqueForeignTokenInit; + + console.log( + '[Unique -> Acala] transaction fees on Acala: %s ACA', + bigIntToDecimals(acaFees, ACALA_DECIMALS), + ); + console.log('[Unique -> Acala] income %s UNQ', bigIntToDecimals(unqIncomeTransfer)); + expect(acaFees == 0n).to.be.true; + expect(unqIncomeTransfer == TRANSFER_AMOUNT).to.be.true; + }, + acalaOptions(), + ); + }); + + it('Should connect to Acala and send UNQ back', async () => { + + // Acala side + await usingApi( + async (api) => { + const destination = { + V1: { + parents: 1, + interior: { + X2: [ + {Parachain: UNIQUE_CHAIN}, + { + AccountId32: { + network: 'Any', + id: randomAccount.addressRaw, + }, + }, + ], + }, + }, + }; + + const id = { + ForeignAsset: 0, + }; + + const destWeight = 50000000; + + const tx = api.tx.xTokens.transfer(id as any, TRANSFER_AMOUNT, destination, destWeight); + const events = await submitTransactionAsync(randomAccount, tx); + const result = getGenericResult(events); + expect(result.success).to.be.true; + + [balanceAcalaTokenFinal] = await getBalance(api, [randomAccount.address]); + { + const {free} = (await api.query.tokens.accounts(randomAccount.addressRaw, id)).toJSON() as any; + balanceUniqueForeignTokenFinal = BigInt(free); + } + + const acaFees = balanceAcalaTokenMiddle - balanceAcalaTokenFinal; + const unqOutcomeTransfer = balanceUniqueForeignTokenMiddle - balanceUniqueForeignTokenFinal; + + console.log( + '[Acala -> Unique] transaction fees on Acala: %s ACA', + bigIntToDecimals(acaFees, ACALA_DECIMALS), + ); + console.log('[Acala -> Unique] outcome %s UNQ', bigIntToDecimals(unqOutcomeTransfer)); + + expect(acaFees > 0).to.be.true; + expect(unqOutcomeTransfer == TRANSFER_AMOUNT).to.be.true; + }, + acalaOptions(), + ); + + // Unique side + await usingApi(async (api) => { + await waitNewBlocks(api, 3); + + [balanceUniqueTokenFinal] = await getBalance(api, [randomAccount.address]); + const actuallyDelivered = balanceUniqueTokenFinal - balanceUniqueTokenMiddle; + expect(actuallyDelivered > 0).to.be.true; + + console.log('[Acala -> Unique] actually delivered %s UNQ', bigIntToDecimals(actuallyDelivered)); + + const unqFees = TRANSFER_AMOUNT - actuallyDelivered; + console.log('[Acala -> Unique] transaction fees on Unique: %s UNQ', bigIntToDecimals(unqFees)); + expect(unqFees == 0n).to.be.true; + }); + }); +}); + +// These tests are relevant only when the foreign asset pallet is disabled +describe_xcm('[XCM] Integration test: Unique rejects non-native tokens', () => { + let alice: IKeyringPair; + + before(async () => { + await usingApi(async (api, privateKeyWrapper) => { + alice = privateKeyWrapper('//Alice'); + }); + }); + + it('Unique rejects tokens from the Relay', async () => { + await usingApi(async (api) => { + const destination = { + V1: { + parents: 0, + interior: {X1: { + Parachain: UNIQUE_CHAIN, + }, + }, + }}; + + const beneficiary = { + V1: { + parents: 0, + interior: {X1: { + AccountId32: { + network: 'Any', + id: alice.addressRaw, + }, + }}, + }, + }; + + const assets = { + V1: [ + { + id: { + Concrete: { + parents: 0, + interior: 'Here', + }, + }, + fun: { + Fungible: 50_000_000_000_000_000n, + }, + }, + ], + }; + + const feeAssetItem = 0; + + const weightLimit = { + Limited: 5_000_000_000, + }; + + const tx = api.tx.xcmPallet.limitedReserveTransferAssets(destination, beneficiary, assets, feeAssetItem, weightLimit); + const events = await submitTransactionAsync(alice, tx); + const result = getGenericResult(events); + expect(result.success).to.be.true; + }, relayOptions()); + + await usingApi(async api => { + const maxWaitBlocks = 3; + const dmpQueueExecutedDownward = await waitEvent( + api, + maxWaitBlocks, + 'dmpQueue', + 'ExecutedDownward', + ); + + expect( + dmpQueueExecutedDownward != null, + '[Relay] dmpQueue.ExecutedDownward event is expected', + ).to.be.true; + + const event = dmpQueueExecutedDownward!.event; + const outcome = event.data[1] as XcmV2TraitsOutcome; + + expect( + outcome.isIncomplete, + '[Relay] The outcome of the XCM should be `Incomplete`', + ).to.be.true; + + const incomplete = outcome.asIncomplete; + expect( + incomplete[1].toString() == 'AssetNotFound', + '[Relay] The XCM error should be `AssetNotFound`', + ).to.be.true; + }); + }); + + it('Unique rejects ACA tokens from Acala', async () => { + await usingApi(async (api) => { + const destination = { + V1: { + parents: 1, + interior: { + X2: [ + {Parachain: UNIQUE_CHAIN}, + { + AccountId32: { + network: 'Any', + id: alice.addressRaw, + }, + }, + ], + }, + }, + }; + + const id = { + Token: 'ACA', + }; + + const destWeight = 50000000; + + const tx = api.tx.xTokens.transfer(id as any, 100_000_000_000, destination, destWeight); + const events = await submitTransactionAsync(alice, tx); + const result = getGenericResult(events); + expect(result.success).to.be.true; + }, acalaOptions()); + + await usingApi(async api => { + const maxWaitBlocks = 3; + const xcmpQueueFailEvent = await waitEvent(api, maxWaitBlocks, 'xcmpQueue', 'Fail'); + + expect( + xcmpQueueFailEvent != null, + '[Acala] xcmpQueue.FailEvent event is expected', + ).to.be.true; + + const event = xcmpQueueFailEvent!.event; + const outcome = event.data[1] as XcmV2TraitsError; + + expect( + outcome.isUntrustedReserveLocation, + '[Acala] The XCM error should be `UntrustedReserveLocation`', + ).to.be.true; + }); + }); +}); + +describe_xcm('[XCM] Integration test: Exchanging UNQ with Moonbeam', () => { + + // Unique constants + let uniqueAlice: IKeyringPair; + let uniqueAssetLocation; + + let randomAccountUnique: IKeyringPair; + let randomAccountMoonbeam: IKeyringPair; + + // Moonbeam constants + let assetId: string; + + const moonbeamKeyring = new Keyring({type: 'ethereum'}); + const alithPrivateKey = '0x5fb92d6e98884f76de468fa3f6278f8807c48bebc13595d45af5bdc4da702133'; + const baltatharPrivateKey = '0x8075991ce870b93a8870eca0c0f91913d12f47948ca0fd25b49c6fa7cdbeee8b'; + const dorothyPrivateKey = '0x39539ab1876910bbf3a223d84a29e28f1cb4e2e456503e7e91ed39b2e7223d68'; + + const alithAccount = moonbeamKeyring.addFromUri(alithPrivateKey, undefined, 'ethereum'); + const baltatharAccount = moonbeamKeyring.addFromUri(baltatharPrivateKey, undefined, 'ethereum'); + const dorothyAccount = moonbeamKeyring.addFromUri(dorothyPrivateKey, undefined, 'ethereum'); + + const councilVotingThreshold = 2; + const technicalCommitteeThreshold = 2; + const votingPeriod = 3; + const delayPeriod = 0; + + const uniqueAssetMetadata = { + name: 'xcUnique', + symbol: 'xcUNQ', + decimals: 18, + isFrozen: false, + minimalBalance: 1, + }; + + let balanceUniqueTokenInit: bigint; + let balanceUniqueTokenMiddle: bigint; + let balanceUniqueTokenFinal: bigint; + let balanceForeignUnqTokenInit: bigint; + let balanceForeignUnqTokenMiddle: bigint; + let balanceForeignUnqTokenFinal: bigint; + let balanceGlmrTokenInit: bigint; + let balanceGlmrTokenMiddle: bigint; + let balanceGlmrTokenFinal: bigint; + + before(async () => { + await usingApi(async (api, privateKeyWrapper) => { + const keyringEth = new Keyring({type: 'ethereum'}); + const keyringSr25519 = new Keyring({type: 'sr25519'}); + + uniqueAlice = privateKeyWrapper('//Alice'); + randomAccountUnique = generateKeyringPair(keyringSr25519); + randomAccountMoonbeam = generateKeyringPair(keyringEth); + + balanceForeignUnqTokenInit = 0n; + }); + + await usingApi( + async (api) => { + + // >>> Sponsoring Dorothy >>> + console.log('Sponsoring Dorothy.......'); + const tx0 = api.tx.balances.transfer(dorothyAccount.address, 11_000_000_000_000_000_000n); + const events0 = await submitTransactionAsync(alithAccount, tx0); + const result0 = getGenericResult(events0); + expect(result0.success).to.be.true; + console.log('Sponsoring Dorothy.......DONE'); + // <<< Sponsoring Dorothy <<< + + const sourceLocation: MultiLocation = api.createType( + 'MultiLocation', + { + parents: 1, + interior: {X1: {Parachain: UNIQUE_CHAIN}}, + }, + ); + + uniqueAssetLocation = {XCM: sourceLocation}; + const existentialDeposit = 1; + const isSufficient = true; + const unitsPerSecond = '1'; + const numAssetsWeightHint = 0; + + const registerTx = api.tx.assetManager.registerForeignAsset( + uniqueAssetLocation, + uniqueAssetMetadata, + existentialDeposit, + isSufficient, + ); + console.log('Encoded proposal for registerAsset is %s', registerTx.method.toHex() || ''); + + const setUnitsTx = api.tx.assetManager.setAssetUnitsPerSecond( + uniqueAssetLocation, + unitsPerSecond, + numAssetsWeightHint, + ); + console.log('Encoded proposal for setAssetUnitsPerSecond is %s', setUnitsTx.method.toHex() || ''); + + const batchCall = api.tx.utility.batchAll([registerTx, setUnitsTx]); + console.log('Encoded proposal for batchCall is %s', batchCall.method.toHex() || ''); + + // >>> Note motion preimage >>> + console.log('Note motion preimage.......'); + const encodedProposal = batchCall?.method.toHex() || ''; + const proposalHash = blake2AsHex(encodedProposal); + console.log('Encoded proposal for batch utility after schedule is %s', encodedProposal); + console.log('Encoded proposal hash for batch utility after schedule is %s', proposalHash); + console.log('Encoded length %d', encodedProposal.length); + + const tx1 = api.tx.democracy.notePreimage(encodedProposal); + const events1 = await submitTransactionAsync(baltatharAccount, tx1); + const result1 = getGenericResult(events1); + expect(result1.success).to.be.true; + console.log('Note motion preimage.......DONE'); + // <<< Note motion preimage <<< + + // >>> Propose external motion through council >>> + console.log('Propose external motion through council.......'); + const externalMotion = api.tx.democracy.externalProposeMajority(proposalHash); + const tx2 = api.tx.councilCollective.propose( + councilVotingThreshold, + externalMotion, + externalMotion.encodedLength, + ); + const events2 = await submitTransactionAsync(baltatharAccount, tx2); + const result2 = getGenericResult(events2); + expect(result2.success).to.be.true; + + const encodedMotion = externalMotion?.method.toHex() || ''; + const motionHash = blake2AsHex(encodedMotion); + console.log('Motion hash is %s', motionHash); + + const tx3 = api.tx.councilCollective.vote(motionHash, 0, true); + { + const events3 = await submitTransactionAsync(dorothyAccount, tx3); + const result3 = getGenericResult(events3); + expect(result3.success).to.be.true; + } + { + const events3 = await submitTransactionAsync(baltatharAccount, tx3); + const result3 = getGenericResult(events3); + expect(result3.success).to.be.true; + } + + const tx4 = api.tx.councilCollective.close(motionHash, 0, 1_000_000_000, externalMotion.encodedLength); + const events4 = await submitTransactionAsync(dorothyAccount, tx4); + const result4 = getGenericResult(events4); + expect(result4.success).to.be.true; + console.log('Propose external motion through council.......DONE'); + // <<< Propose external motion through council <<< + + // >>> Fast track proposal through technical committee >>> + console.log('Fast track proposal through technical committee.......'); + const fastTrack = api.tx.democracy.fastTrack(proposalHash, votingPeriod, delayPeriod); + const tx5 = api.tx.techCommitteeCollective.propose( + technicalCommitteeThreshold, + fastTrack, + fastTrack.encodedLength, + ); + const events5 = await submitTransactionAsync(alithAccount, tx5); + const result5 = getGenericResult(events5); + expect(result5.success).to.be.true; + + const encodedFastTrack = fastTrack?.method.toHex() || ''; + const fastTrackHash = blake2AsHex(encodedFastTrack); + console.log('FastTrack hash is %s', fastTrackHash); + + const proposalIdx = Number(await api.query.techCommitteeCollective.proposalCount()) - 1; + const tx6 = api.tx.techCommitteeCollective.vote(fastTrackHash, proposalIdx, true); + { + const events6 = await submitTransactionAsync(baltatharAccount, tx6); + const result6 = getGenericResult(events6); + expect(result6.success).to.be.true; + } + { + const events6 = await submitTransactionAsync(alithAccount, tx6); + const result6 = getGenericResult(events6); + expect(result6.success).to.be.true; + } + + const tx7 = api.tx.techCommitteeCollective + .close(fastTrackHash, proposalIdx, 1_000_000_000, fastTrack.encodedLength); + const events7 = await submitTransactionAsync(baltatharAccount, tx7); + const result7 = getGenericResult(events7); + expect(result7.success).to.be.true; + console.log('Fast track proposal through technical committee.......DONE'); + // <<< Fast track proposal through technical committee <<< + + // >>> Referendum voting >>> + console.log('Referendum voting.......'); + const tx8 = api.tx.democracy.vote( + 0, + {Standard: {balance: 10_000_000_000_000_000_000n, vote: {aye: true, conviction: 1}}}, + ); + const events8 = await submitTransactionAsync(dorothyAccount, tx8); + const result8 = getGenericResult(events8); + expect(result8.success).to.be.true; + console.log('Referendum voting.......DONE'); + // <<< Referendum voting <<< + + // >>> Acquire Unique AssetId Info on Moonbeam >>> + console.log('Acquire Unique AssetId Info on Moonbeam.......'); + + // Wait for the democracy execute + await waitNewBlocks(api, 5); + + assetId = (await api.query.assetManager.assetTypeId({ + XCM: sourceLocation, + })).toString(); + + console.log('UNQ asset ID is %s', assetId); + console.log('Acquire Unique AssetId Info on Moonbeam.......DONE'); + // >>> Acquire Unique AssetId Info on Moonbeam >>> + + // >>> Sponsoring random Account >>> + console.log('Sponsoring random Account.......'); + const tx10 = api.tx.balances.transfer(randomAccountMoonbeam.address, 11_000_000_000_000_000_000n); + const events10 = await submitTransactionAsync(baltatharAccount, tx10); + const result10 = getGenericResult(events10); + expect(result10.success).to.be.true; + console.log('Sponsoring random Account.......DONE'); + // <<< Sponsoring random Account <<< + + [balanceGlmrTokenInit] = await getBalance(api, [randomAccountMoonbeam.address]); + }, + moonbeamOptions(), + ); + + await usingApi(async (api) => { + const tx0 = api.tx.balances.transfer(randomAccountUnique.address, 10n * TRANSFER_AMOUNT); + const events0 = await submitTransactionAsync(uniqueAlice, tx0); + const result0 = getGenericResult(events0); + expect(result0.success).to.be.true; + + [balanceUniqueTokenInit] = await getBalance(api, [randomAccountUnique.address]); + }); + }); + + it('Should connect and send UNQ to Moonbeam', async () => { + await usingApi(async (api) => { + const currencyId = { + NativeAssetId: 'Here', + }; + const dest = { + V1: { + parents: 1, + interior: { + X2: [ + {Parachain: MOONBEAM_CHAIN}, + {AccountKey20: {network: 'Any', key: randomAccountMoonbeam.address}}, + ], + }, + }, + }; + const amount = TRANSFER_AMOUNT; + const destWeight = 850000000; + + const tx = api.tx.xTokens.transfer(currencyId, amount, dest, destWeight); + const events = await submitTransactionAsync(randomAccountUnique, tx); + const result = getGenericResult(events); + expect(result.success).to.be.true; + + [balanceUniqueTokenMiddle] = await getBalance(api, [randomAccountUnique.address]); + expect(balanceUniqueTokenMiddle < balanceUniqueTokenInit).to.be.true; + + const transactionFees = balanceUniqueTokenInit - balanceUniqueTokenMiddle - TRANSFER_AMOUNT; + console.log('[Unique -> Moonbeam] transaction fees on Unique: %s UNQ', bigIntToDecimals(transactionFees)); + expect(transactionFees > 0).to.be.true; + }); + + await usingApi( + async (api) => { + await waitNewBlocks(api, 3); + + [balanceGlmrTokenMiddle] = await getBalance(api, [randomAccountMoonbeam.address]); + + const glmrFees = balanceGlmrTokenInit - balanceGlmrTokenMiddle; + console.log('[Unique -> Moonbeam] transaction fees on Moonbeam: %s GLMR', bigIntToDecimals(glmrFees)); + expect(glmrFees == 0n).to.be.true; + + const unqRandomAccountAsset = ( + await api.query.assets.account(assetId, randomAccountMoonbeam.address) + ).toJSON()! as any; + + balanceForeignUnqTokenMiddle = BigInt(unqRandomAccountAsset['balance']); + const unqIncomeTransfer = balanceForeignUnqTokenMiddle - balanceForeignUnqTokenInit; + console.log('[Unique -> Moonbeam] income %s UNQ', bigIntToDecimals(unqIncomeTransfer)); + expect(unqIncomeTransfer == TRANSFER_AMOUNT).to.be.true; + }, + moonbeamOptions(), + ); + }); + + it('Should connect to Moonbeam and send UNQ back', async () => { + await usingApi( + async (api) => { + const asset = { + V1: { + id: { + Concrete: { + parents: 1, + interior: { + X1: {Parachain: UNIQUE_CHAIN}, + }, + }, + }, + fun: { + Fungible: TRANSFER_AMOUNT, + }, + }, + }; + const destination = { + V1: { + parents: 1, + interior: { + X2: [ + {Parachain: UNIQUE_CHAIN}, + {AccountId32: {network: 'Any', id: randomAccountUnique.addressRaw}}, + ], + }, + }, + }; + const destWeight = 50000000; + + const tx = api.tx.xTokens.transferMultiasset(asset, destination, destWeight); + const events = await submitTransactionAsync(randomAccountMoonbeam, tx); + const result = getGenericResult(events); + expect(result.success).to.be.true; + + [balanceGlmrTokenFinal] = await getBalance(api, [randomAccountMoonbeam.address]); + + const glmrFees = balanceGlmrTokenMiddle - balanceGlmrTokenFinal; + console.log('[Moonbeam -> Unique] transaction fees on Moonbeam: %s GLMR', bigIntToDecimals(glmrFees)); + expect(glmrFees > 0).to.be.true; + + const unqRandomAccountAsset = ( + await api.query.assets.account(assetId, randomAccountMoonbeam.address) + ).toJSON()! as any; + + expect(unqRandomAccountAsset).to.be.null; + + balanceForeignUnqTokenFinal = 0n; + + const unqOutcomeTransfer = balanceForeignUnqTokenMiddle - balanceForeignUnqTokenFinal; + console.log('[Unique -> Moonbeam] outcome %s UNQ', bigIntToDecimals(unqOutcomeTransfer)); + expect(unqOutcomeTransfer == TRANSFER_AMOUNT).to.be.true; + }, + moonbeamOptions(), + ); + + await usingApi(async (api) => { + await waitNewBlocks(api, 3); + + [balanceUniqueTokenFinal] = await getBalance(api, [randomAccountUnique.address]); + const actuallyDelivered = balanceUniqueTokenFinal - balanceUniqueTokenMiddle; + expect(actuallyDelivered > 0).to.be.true; + + console.log('[Moonbeam -> Unique] actually delivered %s UNQ', bigIntToDecimals(actuallyDelivered)); + + const unqFees = TRANSFER_AMOUNT - actuallyDelivered; + console.log('[Moonbeam -> Unique] transaction fees on Unique: %s UNQ', bigIntToDecimals(unqFees)); + expect(unqFees == 0n).to.be.true; + }); + }); +}); --- a/tests/src/xcmTransfer.test.ts +++ b/tests/src/xcmTransfer.test.ts @@ -78,7 +78,7 @@ let balanceOnKaruraBefore: bigint; await usingApi(async (api) => { - const {free} = (await api.query.tokens.accounts(alice.addressRaw, {ForeignAsset: 0})).toJSON() as any; + const {free} = (await api.query.tokens.accounts(alice.addressRaw, {ForeignAssetId: 0})).toJSON() as any; balanceOnKaruraBefore = free; }, {provider: new WsProvider('ws://127.0.0.1:' + KARURA_PORT)}); @@ -136,7 +136,7 @@ await usingApi(async (api) => { // todo do something about instant sealing, where there might not be any new blocks await waitNewBlocks(api, 3); - const {free} = (await api.query.tokens.accounts(alice.addressRaw, {ForeignAsset: 0})).toJSON() as any; + const {free} = (await api.query.tokens.accounts(alice.addressRaw, {ForeignAssetId: 0})).toJSON() as any; expect(free > balanceOnKaruraBefore).to.be.true; }, {provider: new WsProvider('ws://127.0.0.1:' + KARURA_PORT)}); }); @@ -165,7 +165,7 @@ }; const id = { - ForeignAsset: 0, + ForeignAssetId: 0, }; const amount = TRANSFER_AMOUNT; -- gitstuff