difftreelog
Merge branch 'develop' into chore/fix-warnings
in: master
76 files changed
.docker/Dockerfile-try-runtimediffbeforeafterboth--- a/.docker/Dockerfile-try-runtime
+++ b/.docker/Dockerfile-try-runtime
@@ -46,4 +46,4 @@
echo "Fork from: $REPLICA_FROM\n" && \
cargo build --features=try-runtime,${NETWORK}-runtime --release
-CMD cargo run --features=try-runtime,${NETWORK}-runtime --release -- try-runtime -ltry-runtime::cli=debug --no-spec-check-panic on-runtime-upgrade live --uri $REPLICA_FROM
+CMD cargo run --release --features ${NETWORK}-runtime,try-runtime -- try-runtime --runtime target/release/wbuild/${NETWORK}-runtime/${NETWORK}_runtime.compact.compressed.wasm -lruntime=debug -ltry-runtime::cli=debug on-runtime-upgrade --checks live --uri $REPLICA_FROM
.envdiffbeforeafterboth--- a/.env
+++ b/.env
@@ -5,19 +5,19 @@
STATEMINT_BUILD_BRANCH=release-parachains-v9320
ACALA_BUILD_BRANCH=2.11.0
MOONBEAM_BUILD_BRANCH=runtime-1901
-UNIQUE_MAINNET_BRANCH=release-v930033
+UNIQUE_MAINNET_BRANCH=release-v930033-fix-gas-price
UNIQUE_REPLICA_FROM=wss://eu-ws.unique.network:443
KUSAMA_MAINNET_BRANCH=release-v0.9.35
STATEMINE_BUILD_BRANCH=release-parachains-v9330
KARURA_BUILD_BRANCH=release-karura-2.11.0
MOONRIVER_BUILD_BRANCH=runtime-2000
-QUARTZ_MAINNET_BRANCH=release-v930034
+QUARTZ_MAINNET_BRANCH=release-v930034-fix-gas-price
QUARTZ_REPLICA_FROM=wss://eu-ws-quartz.unique.network:443
UNQWND_MAINNET_BRANCH=release-v0.9.30
WESTMINT_BUILD_BRANCH=parachains-v9330
-OPAL_MAINNET_BRANCH=release-v930034
+OPAL_MAINNET_BRANCH=release-v930034-fix-gas-price
OPAL_REPLICA_FROM=wss://eu-ws-opal.unique.network:443
POLKADOT_LAUNCH_BRANCH=unique-network
.github/workflows/ci-master.ymldiffbeforeafterboth--- a/.github/workflows/ci-master.yml
+++ b/.github/workflows/ci-master.yml
@@ -42,3 +42,6 @@
codestyle:
uses: ./.github/workflows/codestyle.yml
+
+ polkadot-types:
+ uses: ./.github/workflows/polkadot-types.yml
\ No newline at end of file
.github/workflows/polkadot-types.ymldiffbeforeafterboth--- /dev/null
+++ b/.github/workflows/polkadot-types.yml
@@ -0,0 +1,96 @@
+# Integration test in --dev mode
+# https://cryptousetech.atlassian.net/wiki/spaces/CI/pages/2586411104/Integration+tests
+name: Polkadot types
+
+# Triger: only call from main workflow(re-usable workflows)
+on:
+ workflow_call:
+ # Allows you to run this workflow manually from the Actions tab
+ workflow_dispatch:
+
+# on:
+# pull_request:
+# branches: [ 'develop' ]
+# types: [ opened, reopened, synchronize, ready_for_review, converted_to_draft ]
+
+
+# A workflow run is made up of one or more jobs that can run sequentially or in parallel
+jobs:
+
+ polkadot_generate_types:
+ # The type of runner that the job will run on
+ runs-on: [self-hosted-ci,medium]
+ timeout-minutes: 1380
+
+ name: ${{ matrix.network }}
+
+ continue-on-error: true #Do not stop testing of matrix runs failed. As it decided during PR review - it required 50/50& Let's check it with false.
+
+ strategy:
+ matrix:
+ include:
+ - network: sapphire
+ usage: "--sapphire"
+ - network: "opal"
+ usage: ""
+ - network: "quartz"
+ usage: ""
+ - network: "unique"
+ usage: ""
+
+ 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@v2
+
+ - name: Generate ENV related extend file for docker-compose
+ uses: cuchi/jinja2-action@v1.2.0
+ with:
+ template: .docker/docker-compose.tmp-dev.j2
+ output_file: .docker/docker-compose.${{ matrix.network }}.yml
+ variables: |
+ RUST_TOOLCHAIN=${{ env.RUST_TOOLCHAIN }}
+ NETWORK=${{ matrix.network }}
+
+ - name: Show build configuration
+ run: cat .docker/docker-compose.${{ matrix.network }}.yml
+
+ - name: Build the stack
+ run: docker-compose -f ".docker/docker-compose.${{ matrix.network }}.yml" up -d --build --remove-orphans
+
+ - uses: actions/setup-node@v3
+ with:
+ node-version: 16
+
+ - name: Install jq
+ run: sudo apt install jq -y
+
+ - name: Run generate_types_package script
+ working-directory: tests
+ run: |
+ yarn install
+ /bin/bash ./scripts/wait_for_first_block.sh
+ git config --global user.name "Unique"
+ git config --global user.email github-actions@usetech.com
+ /bin/bash ./scripts/generate_types_package.sh --release ${{ matrix.usage }} --push
+ env:
+ RPC_URL: http://127.0.0.1:9933/
+
+ - name: Stop running containers
+ if: always() # run this step always
+ run: docker-compose -f ".docker/docker-compose.${{ matrix.network }}.yml" down
+
+ - name: Remove builder cache
+ if: always() # run this step always
+ run: |
+ docker builder prune -f -a
+ docker system prune -f
+ docker image prune -f -a
.github/workflows/schedule-trigger-for-develop-build.ymldiffbeforeafterboth--- a/.github/workflows/schedule-trigger-for-develop-build.yml
+++ b/.github/workflows/schedule-trigger-for-develop-build.yml
@@ -1,8 +1,8 @@
name: schedule-trigger-for-develop-build
on:
# update the branch ci/develop-scheduler every night
- schedule:
- - cron: '0 1 * * *'
+ # schedule:
+ # - cron: '0 1 * * *'
# or update the branch manually
workflow_dispatch:
# pull_request:
Cargo.lockdiffbeforeafterboth--- a/Cargo.lock
+++ b/Cargo.lock
@@ -2467,7 +2467,7 @@
[[package]]
name = "fc-consensus"
version = "2.0.0-dev"
-source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.36#db60b911813df1d82e60e0de7f3dfa290e60d2f0"
+source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.36#cf1894629c7df1c4dafe58aa773627a3d940da14"
dependencies = [
"async-trait",
"fc-db",
@@ -2486,7 +2486,7 @@
[[package]]
name = "fc-db"
version = "2.0.0-dev"
-source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.36#db60b911813df1d82e60e0de7f3dfa290e60d2f0"
+source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.36#cf1894629c7df1c4dafe58aa773627a3d940da14"
dependencies = [
"fp-storage",
"kvdb-rocksdb",
@@ -2505,7 +2505,7 @@
[[package]]
name = "fc-mapping-sync"
version = "2.0.0-dev"
-source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.36#db60b911813df1d82e60e0de7f3dfa290e60d2f0"
+source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.36#cf1894629c7df1c4dafe58aa773627a3d940da14"
dependencies = [
"fc-db",
"fp-consensus",
@@ -2522,7 +2522,7 @@
[[package]]
name = "fc-rpc"
version = "2.0.0-dev"
-source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.36#db60b911813df1d82e60e0de7f3dfa290e60d2f0"
+source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.36#cf1894629c7df1c4dafe58aa773627a3d940da14"
dependencies = [
"ethereum 0.14.0",
"ethereum-types 0.14.1",
@@ -2565,7 +2565,7 @@
[[package]]
name = "fc-rpc-core"
version = "1.1.0-dev"
-source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.36#db60b911813df1d82e60e0de7f3dfa290e60d2f0"
+source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.36#cf1894629c7df1c4dafe58aa773627a3d940da14"
dependencies = [
"ethereum 0.14.0",
"ethereum-types 0.14.1",
@@ -2730,7 +2730,7 @@
[[package]]
name = "fp-consensus"
version = "2.0.0-dev"
-source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.36#db60b911813df1d82e60e0de7f3dfa290e60d2f0"
+source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.36#cf1894629c7df1c4dafe58aa773627a3d940da14"
dependencies = [
"ethereum 0.14.0",
"parity-scale-codec 3.2.1",
@@ -2742,7 +2742,7 @@
[[package]]
name = "fp-ethereum"
version = "1.0.0-dev"
-source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.36#db60b911813df1d82e60e0de7f3dfa290e60d2f0"
+source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.36#cf1894629c7df1c4dafe58aa773627a3d940da14"
dependencies = [
"ethereum 0.14.0",
"ethereum-types 0.14.1",
@@ -2757,7 +2757,7 @@
[[package]]
name = "fp-evm"
version = "3.0.0-dev"
-source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.36#db60b911813df1d82e60e0de7f3dfa290e60d2f0"
+source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.36#cf1894629c7df1c4dafe58aa773627a3d940da14"
dependencies = [
"evm",
"frame-support",
@@ -2771,7 +2771,7 @@
[[package]]
name = "fp-evm-mapping"
version = "0.1.0"
-source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.36#db60b911813df1d82e60e0de7f3dfa290e60d2f0"
+source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.36#cf1894629c7df1c4dafe58aa773627a3d940da14"
dependencies = [
"frame-support",
"sp-core",
@@ -2780,7 +2780,7 @@
[[package]]
name = "fp-rpc"
version = "3.0.0-dev"
-source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.36#db60b911813df1d82e60e0de7f3dfa290e60d2f0"
+source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.36#cf1894629c7df1c4dafe58aa773627a3d940da14"
dependencies = [
"ethereum 0.14.0",
"ethereum-types 0.14.1",
@@ -2797,7 +2797,7 @@
[[package]]
name = "fp-self-contained"
version = "1.0.0-dev"
-source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.36#db60b911813df1d82e60e0de7f3dfa290e60d2f0"
+source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.36#cf1894629c7df1c4dafe58aa773627a3d940da14"
dependencies = [
"ethereum 0.14.0",
"frame-support",
@@ -2810,7 +2810,7 @@
[[package]]
name = "fp-storage"
version = "2.0.0"
-source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.36#db60b911813df1d82e60e0de7f3dfa290e60d2f0"
+source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.36#cf1894629c7df1c4dafe58aa773627a3d940da14"
dependencies = [
"parity-scale-codec 3.2.1",
"serde",
@@ -5682,7 +5682,7 @@
[[package]]
name = "pallet-base-fee"
version = "1.0.0"
-source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.36#db60b911813df1d82e60e0de7f3dfa290e60d2f0"
+source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.36#cf1894629c7df1c4dafe58aa773627a3d940da14"
dependencies = [
"fp-evm",
"frame-support",
@@ -5918,7 +5918,7 @@
[[package]]
name = "pallet-ethereum"
version = "4.0.0-dev"
-source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.36#db60b911813df1d82e60e0de7f3dfa290e60d2f0"
+source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.36#cf1894629c7df1c4dafe58aa773627a3d940da14"
dependencies = [
"ethereum 0.14.0",
"ethereum-types 0.14.1",
@@ -5946,7 +5946,7 @@
[[package]]
name = "pallet-evm"
version = "6.0.0-dev"
-source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.36#db60b911813df1d82e60e0de7f3dfa290e60d2f0"
+source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.36#cf1894629c7df1c4dafe58aa773627a3d940da14"
dependencies = [
"environmental",
"evm",
@@ -6032,7 +6032,7 @@
[[package]]
name = "pallet-evm-precompile-simple"
version = "2.0.0-dev"
-source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.36#db60b911813df1d82e60e0de7f3dfa290e60d2f0"
+source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.36#cf1894629c7df1c4dafe58aa773627a3d940da14"
dependencies = [
"fp-evm",
"ripemd",
@@ -12965,6 +12965,7 @@
"sp-core",
"sp-finality-grandpa",
"sp-inherents",
+ "sp-io",
"sp-keystore",
"sp-offchain",
"sp-runtime",
crates/evm-coder/procedural/src/abi_derive/derive_enum.rsdiffbeforeafterboth--- a/crates/evm-coder/procedural/src/abi_derive/derive_enum.rs
+++ b/crates/evm-coder/procedural/src/abi_derive/derive_enum.rs
@@ -143,8 +143,7 @@
)
}
-pub fn check_and_count_options(de: &syn::DataEnum) -> syn::Result<usize> {
- let mut count = 0;
+pub fn check_enum_fields(de: &syn::DataEnum) -> syn::Result<()> {
for v in de.variants.iter() {
if !v.fields.is_empty() {
return Err(syn::Error::new(
@@ -156,12 +155,10 @@
v.ident.span(),
"Enumeration options should not have an explicit specified value",
));
- } else {
- count += 1;
}
}
- Ok(count)
+ Ok(())
}
pub fn check_repr_u8(name: &syn::Ident, attrs: &[syn::Attribute]) -> syn::Result<()> {
crates/evm-coder/procedural/src/abi_derive/mod.rsdiffbeforeafterboth--- a/crates/evm-coder/procedural/src/abi_derive/mod.rs
+++ b/crates/evm-coder/procedural/src/abi_derive/mod.rs
@@ -70,6 +70,7 @@
) -> syn::Result<proc_macro2::TokenStream> {
let name = &ast.ident;
check_repr_u8(name, &ast.attrs)?;
+ check_enum_fields(de)?;
let docs = extract_docs(&ast.attrs)?;
let enum_options = de.variants.iter();
node/cli/Cargo.tomldiffbeforeafterboth--- a/node/cli/Cargo.toml
+++ b/node/cli/Cargo.toml
@@ -122,6 +122,10 @@
git = "https://github.com/paritytech/substrate"
branch = "polkadot-v0.9.36"
+[dependencies.sp-io]
+git = "https://github.com/paritytech/substrate"
+branch = "polkadot-v0.9.36"
+
[dependencies.sp-finality-grandpa]
git = "https://github.com/paritytech/substrate"
branch = "polkadot-v0.9.36"
node/cli/src/command.rsdiffbeforeafterboth--- a/node/cli/src/command.rs
+++ b/node/cli/src/command.rs
@@ -412,6 +412,7 @@
#[cfg(feature = "try-runtime")]
Some(Subcommand::TryRuntime(cmd)) => {
use std::{future::Future, pin::Pin};
+ use sc_executor::{sp_wasm_interface::ExtendedHostFunctions, NativeExecutionDispatch};
let runner = cli.create_runner(cmd)?;
@@ -429,12 +430,21 @@
Ok((
match config.chain_spec.runtime_id() {
#[cfg(feature = "unique-runtime")]
- RuntimeId::Unique => Box::pin(cmd.run::<Block, UniqueRuntimeExecutor>(config)),
+ RuntimeId::Unique => Box::pin(cmd.run::<Block, ExtendedHostFunctions<
+ sp_io::SubstrateHostFunctions,
+ <UniqueRuntimeExecutor as NativeExecutionDispatch>::ExtendHostFunctions,
+ >>()),
#[cfg(feature = "quartz-runtime")]
- RuntimeId::Quartz => Box::pin(cmd.run::<Block, QuartzRuntimeExecutor>(config)),
+ RuntimeId::Quartz => Box::pin(cmd.run::<Block, ExtendedHostFunctions<
+ sp_io::SubstrateHostFunctions,
+ <QuartzRuntimeExecutor as NativeExecutionDispatch>::ExtendHostFunctions,
+ >>()),
- RuntimeId::Opal => Box::pin(cmd.run::<Block, OpalRuntimeExecutor>(config)),
+ RuntimeId::Opal => Box::pin(cmd.run::<Block, ExtendedHostFunctions<
+ sp_io::SubstrateHostFunctions,
+ <OpalRuntimeExecutor as NativeExecutionDispatch>::ExtendHostFunctions,
+ >>()),
RuntimeId::Unknown(chain) => return Err(no_runtime_err!(chain).into()),
},
task_manager,
node/cli/src/service.rsdiffbeforeafterboth--- a/node/cli/src/service.rs
+++ b/node/cli/src/service.rs
@@ -106,7 +106,12 @@
#[cfg(feature = "unique-runtime")]
impl NativeExecutionDispatch for UniqueRuntimeExecutor {
+ /// Only enable the benchmarking host functions when we actually want to benchmark.
+ #[cfg(feature = "runtime-benchmarks")]
type ExtendHostFunctions = frame_benchmarking::benchmarking::HostFunctions;
+ /// Otherwise we only use the default Substrate host functions.
+ #[cfg(not(feature = "runtime-benchmarks"))]
+ type ExtendHostFunctions = ();
fn dispatch(method: &str, data: &[u8]) -> Option<Vec<u8>> {
unique_runtime::api::dispatch(method, data)
@@ -119,7 +124,12 @@
#[cfg(feature = "quartz-runtime")]
impl NativeExecutionDispatch for QuartzRuntimeExecutor {
+ /// Only enable the benchmarking host functions when we actually want to benchmark.
+ #[cfg(feature = "runtime-benchmarks")]
type ExtendHostFunctions = frame_benchmarking::benchmarking::HostFunctions;
+ /// Otherwise we only use the default Substrate host functions.
+ #[cfg(not(feature = "runtime-benchmarks"))]
+ type ExtendHostFunctions = ();
fn dispatch(method: &str, data: &[u8]) -> Option<Vec<u8>> {
quartz_runtime::api::dispatch(method, data)
@@ -131,7 +141,12 @@
}
impl NativeExecutionDispatch for OpalRuntimeExecutor {
+ /// Only enable the benchmarking host functions when we actually want to benchmark.
+ #[cfg(feature = "runtime-benchmarks")]
type ExtendHostFunctions = frame_benchmarking::benchmarking::HostFunctions;
+ /// Otherwise we only use the default Substrate host functions.
+ #[cfg(not(feature = "runtime-benchmarks"))]
+ type ExtendHostFunctions = ();
fn dispatch(method: &str, data: &[u8]) -> Option<Vec<u8>> {
opal_runtime::api::dispatch(method, data)
pallets/common/src/eth.rsdiffbeforeafterboth--- a/pallets/common/src/eth.rs
+++ b/pallets/common/src/eth.rs
@@ -127,7 +127,7 @@
pub struct OptionCrossAddress {
/// Whether or not this CrossAdress is valid and has meaning.
pub status: bool,
- /// The underlying CrossAddress. If the status is false, can be set to whatever.
+ /// The underlying CrossAddress value. If the status is false, can be set to whatever.
pub value: CrossAddress,
}
pallets/evm-contract-helpers/src/stubs/ContractHelpers.rawdiffbeforeafterbothbinary blob — no preview
pallets/evm-contract-helpers/src/stubs/ContractHelpers.soldiffbeforeafterboth--- a/pallets/evm-contract-helpers/src/stubs/ContractHelpers.sol
+++ b/pallets/evm-contract-helpers/src/stubs/ContractHelpers.sol
@@ -283,6 +283,8 @@
/// Ethereum representation of Optional value with CrossAddress.
struct OptionCrossAddress {
+ /// TODO: field description
bool status;
+ /// TODO: field description
CrossAddress value;
}
pallets/nonfungible/src/benchmarking.rsdiffbeforeafterboth--- a/pallets/nonfungible/src/benchmarking.rs
+++ b/pallets/nonfungible/src/benchmarking.rs
@@ -228,7 +228,7 @@
owner: sub; collection: collection(owner); owner: cross_from_sub;
operator: cross_sub;
};
- }: {<Pallet<T>>::set_allowance_for_all(&collection, &owner, &operator, true)}
+ }: {<Pallet<T>>::set_allowance_for_all(&collection, &owner, &operator, true)?}
allowance_for_all {
bench_init!{
pallets/refungible/src/benchmarking.rsdiffbeforeafterboth--- a/pallets/refungible/src/benchmarking.rs
+++ b/pallets/refungible/src/benchmarking.rs
@@ -22,21 +22,17 @@
use frame_benchmarking::{benchmarks, account};
use pallet_common::{
bench_init,
- benchmarking::{create_collection_raw, property_key, property_value, create_data},
+ benchmarking::{create_collection_raw, property_key, property_value},
};
-use sp_core::H160;
use sp_std::prelude::*;
-use up_data_structs::{
- CollectionMode, MAX_ITEMS_PER_BATCH, MAX_PROPERTIES_PER_ITEM, CUSTOM_DATA_LIMIT,
- budget::Unlimited,
-};
+use up_data_structs::{CollectionMode, MAX_ITEMS_PER_BATCH, MAX_PROPERTIES_PER_ITEM, budget::Unlimited};
const SEED: u32 = 1;
-fn create_max_item_data<CrossAccountId: Ord>(
- users: impl IntoIterator<Item = (CrossAccountId, u128)>,
-) -> CreateItemData<CrossAccountId> {
- CreateItemData {
+fn create_max_item_data<T: Config>(
+ users: impl IntoIterator<Item = (T::CrossAccountId, u128)>,
+) -> CreateItemData<T> {
+ CreateItemData::<T> {
users: users
.into_iter()
.collect::<BTreeMap<_, _>>()
@@ -51,7 +47,7 @@
sender: &T::CrossAccountId,
users: impl IntoIterator<Item = (T::CrossAccountId, u128)>,
) -> Result<TokenId, DispatchError> {
- let data: CreateItemData<T::CrossAccountId> = create_max_item_data(users);
+ let data: CreateItemData<T> = create_max_item_data::<T>(users);
<Pallet<T>>::create_item(&collection, sender, data, &Unlimited)?;
Ok(TokenId(<TokensMinted<T>>::get(&collection.id)))
}
@@ -83,7 +79,7 @@
owner: sub; collection: collection(owner);
sender: cross_from_sub(owner); to: cross_sub;
};
- let data = (0..b).map(|_| create_max_item_data([(to.clone(), 200)])).collect();
+ let data = (0..b).map(|_| create_max_item_data::<T>([(to.clone(), 200)])).collect();
}: {<Pallet<T>>::create_multiple_items(&collection, &sender, data, &Unlimited)?}
create_multiple_items_ex_multiple_items {
@@ -94,7 +90,7 @@
};
let data = (0..b).map(|t| {
bench_init!(to: cross_sub(t););
- create_max_item_data([(to, 200)])
+ create_max_item_data::<T>([(to, 200)])
}).collect();
}: {<Pallet<T>>::create_multiple_items(&collection, &sender, data, &Unlimited)?}
@@ -104,7 +100,7 @@
owner: sub; collection: collection(owner);
sender: cross_from_sub(owner);
};
- let data = vec![create_max_item_data((0..b).map(|u| {
+ let data = vec![create_max_item_data::<T>((0..b).map(|u| {
bench_init!(to: cross_sub(u););
(to, 200)
}))].try_into().unwrap();
@@ -296,7 +292,7 @@
owner: sub; collection: collection(owner); owner: cross_from_sub;
operator: cross_sub;
};
- }: {<Pallet<T>>::set_allowance_for_all(&collection, &owner, &operator, true)}
+ }: {<Pallet<T>>::set_allowance_for_all(&collection, &owner, &operator, true)?}
allowance_for_all {
bench_init!{
pallets/refungible/src/erc_token.rsdiffbeforeafterboth--- a/pallets/refungible/src/erc_token.rs
+++ b/pallets/refungible/src/erc_token.rs
@@ -43,6 +43,9 @@
TotalSupply, weights::WeightInfo,
};
+/// Refungible token handle contains information about token's collection and id
+///
+/// RefungibleTokenHandle doesn't check token's existance upon creation
pub struct RefungibleTokenHandle<T: Config>(pub RefungibleHandle<T>, pub TokenId);
#[solidity_interface(name = ERC1633)]
runtime/common/ethereum/sponsoring.rsdiffbeforeafterboth--- a/runtime/common/ethereum/sponsoring.rs
+++ b/runtime/common/ethereum/sponsoring.rs
@@ -32,14 +32,22 @@
Config as FungibleConfig,
erc::{UniqueFungibleCall, ERC20Call},
};
-use pallet_refungible::Config as RefungibleConfig;
+use pallet_refungible::{
+ Config as RefungibleConfig,
+ erc::UniqueRefungibleCall,
+ erc_token::{RefungibleTokenHandle, UniqueRefungibleTokenCall},
+ RefungibleHandle,
+};
use pallet_unique::Config as UniqueConfig;
use sp_std::prelude::*;
-use up_data_structs::{CollectionMode, CreateItemData, CreateNftData, TokenId};
+use up_data_structs::{
+ CollectionMode, CreateItemData, CreateNftData, mapping::TokenAddressMapping, TokenId,
+};
use up_sponsorship::SponsorshipHandler;
-
use crate::{Runtime, runtime_common::sponsoring::*};
+mod refungible;
+
pub type EvmSponsorshipHandler = (
UniqueEthSponsorshipHandler<Runtime>,
pallet_evm_contract_helpers::HelpersContractSponsoring<Runtime>,
@@ -53,80 +61,163 @@
who: &T::CrossAccountId,
call_context: &CallContext,
) -> Option<T::CrossAccountId> {
- let collection_id = map_eth_to_id(&call_context.contract_address)?;
- let collection = <CollectionHandle<T>>::new(collection_id)?;
- let sponsor = collection.sponsorship.sponsor()?.clone();
- let (method_id, mut reader) = AbiReader::new_call(&call_context.input).ok()?;
- Some(T::CrossAccountId::from_sub(match &collection.mode {
- CollectionMode::NFT => {
- let call = <UniqueNFTCall<T>>::parse(method_id, &mut reader).ok()??;
- match call {
- UniqueNFTCall::TokenProperties(TokenPropertiesCall::SetProperty {
- token_id,
- key,
- value,
- ..
- }) => {
- let token_id: TokenId = token_id.try_into().ok()?;
- withdraw_set_token_property::<T>(
+ if let Some(collection_id) = map_eth_to_id(&call_context.contract_address) {
+ let collection = <CollectionHandle<T>>::new(collection_id)?;
+ let sponsor = collection.sponsorship.sponsor()?.clone();
+ let (method_id, mut reader) = AbiReader::new_call(&call_context.input).ok()?;
+ Some(T::CrossAccountId::from_sub(match &collection.mode {
+ CollectionMode::NFT => {
+ let call = <UniqueNFTCall<T>>::parse(method_id, &mut reader).ok()??;
+ match call {
+ UniqueNFTCall::TokenProperties(TokenPropertiesCall::SetProperty {
+ token_id,
+ key,
+ value,
+ ..
+ }) => {
+ let token_id: TokenId = token_id.try_into().ok()?;
+ withdraw_set_token_property::<T>(
+ &collection,
+ &who,
+ &token_id,
+ key.len() + value.len(),
+ )
+ .map(|()| sponsor)
+ }
+ UniqueNFTCall::ERC721UniqueExtensions(
+ ERC721UniqueExtensionsCall::Transfer { token_id, .. },
+ ) => {
+ let token_id: TokenId = token_id.try_into().ok()?;
+ withdraw_transfer::<T>(&collection, &who, &token_id).map(|()| sponsor)
+ }
+ UniqueNFTCall::ERC721UniqueMintable(
+ ERC721UniqueMintableCall::Mint { .. }
+ | ERC721UniqueMintableCall::MintCheckId { .. }
+ | ERC721UniqueMintableCall::MintWithTokenUri { .. }
+ | ERC721UniqueMintableCall::MintWithTokenUriCheckId { .. },
+ ) => withdraw_create_item::<T>(
&collection,
&who,
- &token_id,
- key.len() + value.len(),
+ &CreateItemData::NFT(CreateNftData::default()),
)
- .map(|()| sponsor)
- }
- UniqueNFTCall::ERC721UniqueExtensions(
- ERC721UniqueExtensionsCall::Transfer { token_id, .. },
- ) => {
- let token_id: TokenId = token_id.try_into().ok()?;
- withdraw_transfer::<T>(&collection, &who, &token_id).map(|()| sponsor)
+ .map(|()| sponsor),
+ UniqueNFTCall::ERC721(ERC721Call::TransferFrom {
+ token_id, from, ..
+ }) => {
+ let token_id: TokenId = token_id.try_into().ok()?;
+ let from = T::CrossAccountId::from_eth(from);
+ withdraw_transfer::<T>(&collection, &from, &token_id).map(|()| sponsor)
+ }
+ UniqueNFTCall::ERC721(ERC721Call::Approve { token_id, .. }) => {
+ let token_id: TokenId = token_id.try_into().ok()?;
+ withdraw_approve::<T>(&collection, who.as_sub(), &token_id)
+ .map(|()| sponsor)
+ }
+ _ => None,
}
- UniqueNFTCall::ERC721UniqueMintable(
- ERC721UniqueMintableCall::Mint { .. }
- | ERC721UniqueMintableCall::MintCheckId { .. }
- | ERC721UniqueMintableCall::MintWithTokenUri { .. }
- | ERC721UniqueMintableCall::MintWithTokenUriCheckId { .. },
- ) => withdraw_create_item::<T>(
- &collection,
- &who,
- &CreateItemData::NFT(CreateNftData::default()),
- )
- .map(|()| sponsor),
- UniqueNFTCall::ERC721(ERC721Call::TransferFrom { token_id, from, .. }) => {
- let token_id: TokenId = token_id.try_into().ok()?;
- let from = T::CrossAccountId::from_eth(from);
- withdraw_transfer::<T>(&collection, &from, &token_id).map(|()| sponsor)
- }
- UniqueNFTCall::ERC721(ERC721Call::Approve { token_id, .. }) => {
- let token_id: TokenId = token_id.try_into().ok()?;
- withdraw_approve::<T>(&collection, who.as_sub(), &token_id)
- .map(|()| sponsor)
- }
- _ => None,
}
- }
- CollectionMode::Fungible(_) => {
- let call = <UniqueFungibleCall<T>>::parse(method_id, &mut reader).ok()??;
- #[allow(clippy::single_match)]
- match call {
- UniqueFungibleCall::ERC20(ERC20Call::Transfer { .. }) => {
- withdraw_transfer::<T>(&collection, who, &TokenId::default())
- .map(|()| sponsor)
- }
- UniqueFungibleCall::ERC20(ERC20Call::TransferFrom { from, .. }) => {
- let from = T::CrossAccountId::from_eth(from);
- withdraw_transfer::<T>(&collection, &from, &TokenId::default())
- .map(|()| sponsor)
+ CollectionMode::ReFungible => {
+ let call = <UniqueRefungibleCall<T>>::parse(method_id, &mut reader).ok()??;
+ refungible::call_sponsor(call, collection, who).map(|()| sponsor)
+ }
+ CollectionMode::Fungible(_) => {
+ let call = <UniqueFungibleCall<T>>::parse(method_id, &mut reader).ok()??;
+ match call {
+ UniqueFungibleCall::ERC20(ERC20Call::Transfer { .. }) => {
+ withdraw_transfer::<T>(&collection, who, &TokenId::default())
+ .map(|()| sponsor)
+ }
+ UniqueFungibleCall::ERC20(ERC20Call::TransferFrom { from, .. }) => {
+ let from = T::CrossAccountId::from_eth(from);
+ withdraw_transfer::<T>(&collection, &from, &TokenId::default())
+ .map(|()| sponsor)
+ }
+ UniqueFungibleCall::ERC20(ERC20Call::Approve { .. }) => {
+ withdraw_approve::<T>(&collection, who.as_sub(), &TokenId::default())
+ .map(|()| sponsor)
+ }
+ _ => None,
}
- UniqueFungibleCall::ERC20(ERC20Call::Approve { .. }) => {
- withdraw_approve::<T>(&collection, who.as_sub(), &TokenId::default())
- .map(|()| sponsor)
- }
- _ => None,
}
+ }?))
+ } else {
+ let (collection_id, token_id) =
+ T::EvmTokenAddressMapping::address_to_token(&call_context.contract_address)?;
+ let collection = <CollectionHandle<T>>::new(collection_id)?;
+ if collection.mode != CollectionMode::ReFungible {
+ return None;
}
- _ => None,
- }?))
+ let sponsor = collection.sponsorship.sponsor()?.clone();
+ let rft_collection = RefungibleHandle::cast(collection);
+ // Token existance isn't checked at this point and should be checked in `withdraw` method.
+ let token = RefungibleTokenHandle(rft_collection, token_id);
+
+ let (method_id, mut reader) = AbiReader::new_call(&call_context.input).ok()?;
+ let call = <UniqueRefungibleTokenCall<T>>::parse(method_id, &mut reader).ok()??;
+ Some(T::CrossAccountId::from_sub(
+ refungible::token_call_sponsor(call, token, who).map(|()| sponsor)?,
+ ))
+ }
+ }
+}
+
+mod common {
+ use super::*;
+
+ use pallet_common::erc::{CollectionCall};
+
+ pub fn collection_call_sponsor<T>(
+ call: CollectionCall<T>,
+ _collection: CollectionHandle<T>,
+ _who: &T::CrossAccountId,
+ ) -> Option<()>
+ where
+ T: UniqueConfig + FungibleConfig + NonfungibleConfig + RefungibleConfig,
+ {
+ use CollectionCall::*;
+
+ match call {
+ // Readonly
+ ERC165Call(_, _)
+ | CollectionProperty { .. }
+ | CollectionProperties { .. }
+ | HasCollectionPendingSponsor
+ | CollectionSponsor
+ | ContractAddress
+ | AllowlistedCross { .. }
+ | IsOwnerOrAdminEth { .. }
+ | IsOwnerOrAdminCross { .. }
+ | CollectionOwner
+ | CollectionAdmins
+ | CollectionLimits
+ | CollectionNestingRestrictedIds
+ | CollectionNestingPermissions
+ | UniqueCollectionType => None,
+
+ // Not sponsored
+ AddToCollectionAllowList { .. }
+ | AddToCollectionAllowListCross { .. }
+ | RemoveFromCollectionAllowList { .. }
+ | RemoveFromCollectionAllowListCross { .. }
+ | AddCollectionAdminCross { .. }
+ | RemoveCollectionAdminCross { .. }
+ | AddCollectionAdmin { .. }
+ | RemoveCollectionAdmin { .. }
+ | SetNestingBool { .. }
+ | SetNesting { .. }
+ | SetCollectionAccess { .. }
+ | SetCollectionMintMode { .. }
+ | SetOwner { .. }
+ | ChangeCollectionOwnerCross { .. }
+ | SetCollectionProperty { .. }
+ | SetCollectionProperties { .. }
+ | DeleteCollectionProperty { .. }
+ | DeleteCollectionProperties { .. }
+ | SetCollectionSponsor { .. }
+ | SetCollectionSponsorCross { .. }
+ | SetCollectionLimit { .. }
+ | ConfirmCollectionSponsorship
+ | RemoveCollectionSponsor => None,
+ }
}
}
runtime/common/ethereum/sponsoring/refungible.rsdiffbeforeafterboth--- /dev/null
+++ b/runtime/common/ethereum/sponsoring/refungible.rs
@@ -0,0 +1,381 @@
+// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.
+// This file is part of Unique Network.
+
+// Unique Network is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// Unique Network is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
+
+//! Implements EVM sponsoring logic via TransactionValidityHack
+
+use core::convert::TryInto;
+use pallet_common::CollectionHandle;
+use pallet_evm::account::CrossAccountId;
+use pallet_fungible::Config as FungibleConfig;
+use pallet_refungible::Config as RefungibleConfig;
+use pallet_nonfungible::Config as NonfungibleConfig;
+use pallet_unique::Config as UniqueConfig;
+use up_data_structs::{CreateItemData, CreateNftData, TokenId};
+
+use super::common;
+use crate::runtime_common::sponsoring::*;
+
+use pallet_refungible::{
+ erc::{
+ ERC721BurnableCall, ERC721Call, ERC721EnumerableCall, ERC721MetadataCall,
+ ERC721UniqueExtensionsCall, ERC721UniqueMintableCall, TokenPropertiesCall,
+ UniqueRefungibleCall,
+ },
+ erc_token::{
+ ERC1633Call, ERC20Call, ERC20UniqueExtensionsCall, RefungibleTokenHandle,
+ UniqueRefungibleTokenCall,
+ },
+};
+
+pub fn call_sponsor<T>(
+ call: UniqueRefungibleCall<T>,
+ collection: CollectionHandle<T>,
+ who: &T::CrossAccountId,
+) -> Option<()>
+where
+ T: UniqueConfig + FungibleConfig + NonfungibleConfig + RefungibleConfig,
+{
+ use UniqueRefungibleCall::*;
+
+ match call {
+ // Readonly
+ ERC165Call(_, _) => None,
+
+ ERC721Enumerable(call) => erc721::enumerable_call_sponsor(call, collection, who),
+ ERC721Burnable(call) => erc721::burnable_call_sponsor(call, collection, who),
+ ERC721Metadata(call) => erc721::metadata_call_sponsor(call, collection, who),
+ Collection(call) => common::collection_call_sponsor(call, collection, who),
+ ERC721(call) => erc721::call_sponsor(call, collection, who),
+ ERC721UniqueExtensions(call) => {
+ erc721::unique_extensions_call_sponsor(call, collection, who)
+ }
+ ERC721UniqueMintable(call) => erc721::unique_mintable_call_sponsor(call, collection, who),
+ TokenProperties(call) => token_properties_call_sponsor(call, collection, who),
+ }
+}
+
+pub fn token_properties_call_sponsor<T>(
+ call: TokenPropertiesCall<T>,
+ collection: CollectionHandle<T>,
+ who: &T::CrossAccountId,
+) -> Option<()>
+where
+ T: UniqueConfig + FungibleConfig + NonfungibleConfig + RefungibleConfig,
+{
+ use TokenPropertiesCall::*;
+
+ match call {
+ // Readonly
+ ERC165Call(_, _) | Property { .. } | TokenPropertyPermissions => None,
+
+ // Not sponsored
+ SetTokenPropertyPermission { .. }
+ | SetTokenPropertyPermissions { .. }
+ | SetProperties { .. }
+ | DeleteProperty { .. }
+ | DeleteProperties { .. } => None,
+
+ SetProperty {
+ token_id,
+ key,
+ value,
+ ..
+ } => {
+ let token_id = TokenId::try_from(token_id).ok()?;
+ withdraw_set_token_property::<T>(&collection, &who, &token_id, key.len() + value.len())
+ }
+ }
+}
+
+pub fn token_call_sponsor<T>(
+ call: UniqueRefungibleTokenCall<T>,
+ token: RefungibleTokenHandle<T>,
+ who: &T::CrossAccountId,
+) -> Option<()>
+where
+ T: UniqueConfig + FungibleConfig + NonfungibleConfig + RefungibleConfig,
+{
+ use UniqueRefungibleTokenCall::*;
+
+ match call {
+ // Readonly
+ ERC165Call(_, _) => None,
+
+ ERC20(call) => erc20::call_sponsor(call, token, who),
+ ERC20UniqueExtensions(call) => erc20::unique_extensions_call_sponsor(call, token, who),
+ ERC1633(call) => erc1633::call_sponsor(call, token, who),
+ }
+}
+
+mod erc721 {
+ use super::*;
+
+ pub fn call_sponsor<T>(
+ call: ERC721Call<T>,
+ collection: CollectionHandle<T>,
+ _who: &T::CrossAccountId,
+ ) -> Option<()>
+ where
+ T: UniqueConfig + FungibleConfig + NonfungibleConfig + RefungibleConfig,
+ {
+ use ERC721Call::*;
+
+ match call {
+ // Readonly
+ ERC165Call(_, _)
+ | BalanceOf { .. }
+ | OwnerOf { .. }
+ | GetApproved { .. }
+ | IsApprovedForAll { .. }
+ | CollectionHelperAddress => None,
+
+ // Not sponsored
+ SafeTransferFromWithData { .. }
+ | SafeTransferFrom { .. }
+ | SetApprovalForAll { .. } => None,
+
+ TransferFrom { token_id, from, .. } => {
+ let token_id = TokenId::try_from(token_id).ok()?;
+ let from = T::CrossAccountId::from_eth(from);
+ withdraw_transfer::<T>(&collection, &from, &token_id)
+ }
+
+ // Not supported
+ Approve { .. } => None,
+ }
+ }
+
+ pub fn enumerable_call_sponsor<T>(
+ call: ERC721EnumerableCall<T>,
+ _collection: CollectionHandle<T>,
+ _who: &T::CrossAccountId,
+ ) -> Option<()>
+ where
+ T: UniqueConfig + FungibleConfig + NonfungibleConfig + RefungibleConfig,
+ {
+ use ERC721EnumerableCall::*;
+
+ match call {
+ // Readonly
+ ERC165Call(_, _) | TokenByIndex { .. } | TokenOfOwnerByIndex { .. } | TotalSupply => {
+ None
+ }
+ }
+ }
+
+ pub fn burnable_call_sponsor<T>(
+ call: ERC721BurnableCall<T>,
+ _collection: CollectionHandle<T>,
+ _who: &T::CrossAccountId,
+ ) -> Option<()>
+ where
+ T: UniqueConfig + FungibleConfig + NonfungibleConfig + RefungibleConfig,
+ {
+ use ERC721BurnableCall::*;
+
+ match call {
+ // Readonly
+ ERC165Call(_, _) => None,
+
+ // Not sponsored
+ Burn { .. } => None,
+ }
+ }
+
+ pub fn metadata_call_sponsor<T>(
+ call: ERC721MetadataCall<T>,
+ _collection: CollectionHandle<T>,
+ _who: &T::CrossAccountId,
+ ) -> Option<()>
+ where
+ T: UniqueConfig + FungibleConfig + NonfungibleConfig + RefungibleConfig,
+ {
+ use ERC721MetadataCall::*;
+
+ match call {
+ // Readonly
+ ERC165Call(_, _) | NameProxy | SymbolProxy | TokenUri { .. } => None,
+ }
+ }
+
+ pub fn unique_extensions_call_sponsor<T>(
+ call: ERC721UniqueExtensionsCall<T>,
+ collection: CollectionHandle<T>,
+ who: &T::CrossAccountId,
+ ) -> Option<()>
+ where
+ T: UniqueConfig + FungibleConfig + NonfungibleConfig + RefungibleConfig,
+ {
+ use ERC721UniqueExtensionsCall::*;
+
+ match call {
+ // Readonly
+ ERC165Call(_, _)
+ | Name
+ | Symbol
+ | Description
+ | CrossOwnerOf { .. }
+ | Properties { .. }
+ | NextTokenId
+ | TokenContractAddress { .. } => None,
+
+ // Not sponsored
+ BurnFrom { .. }
+ | BurnFromCross { .. }
+ | MintBulk { .. }
+ | MintBulkWithTokenUri { .. } => None,
+
+ MintCross { .. } => withdraw_create_item::<T>(
+ &collection,
+ &who,
+ &CreateItemData::NFT(CreateNftData::default()),
+ ),
+
+ TransferCross { token_id, .. }
+ | TransferFromCross { token_id, .. }
+ | Transfer { token_id, .. } => {
+ let token_id = TokenId::try_from(token_id).ok()?;
+ withdraw_transfer::<T>(&collection, &who, &token_id)
+ }
+ }
+ }
+
+ pub fn unique_mintable_call_sponsor<T>(
+ call: ERC721UniqueMintableCall<T>,
+ collection: CollectionHandle<T>,
+ who: &T::CrossAccountId,
+ ) -> Option<()>
+ where
+ T: UniqueConfig + FungibleConfig + NonfungibleConfig + RefungibleConfig,
+ {
+ use ERC721UniqueMintableCall::*;
+
+ match call {
+ // Readonly
+ ERC165Call(_, _) | MintingFinished => None,
+
+ // Not sponsored
+ FinishMinting => None,
+
+ Mint { .. }
+ | MintCheckId { .. }
+ | MintWithTokenUri { .. }
+ | MintWithTokenUriCheckId { .. } => withdraw_create_item::<T>(
+ &collection,
+ &who,
+ &CreateItemData::NFT(CreateNftData::default()),
+ ),
+ }
+ }
+}
+
+/// Module for methods of refungible token
+///
+/// Existance of token should be checked before searching for sponsor
+/// because RefungibleTokenHandle doesn't check token's existence upon creation
+mod erc20 {
+ use super::*;
+
+ pub fn call_sponsor<T>(
+ call: ERC20Call<T>,
+ token: RefungibleTokenHandle<T>,
+ who: &T::CrossAccountId,
+ ) -> Option<()>
+ where
+ T: UniqueConfig + FungibleConfig + NonfungibleConfig + RefungibleConfig,
+ {
+ use ERC20Call::*;
+
+ match call {
+ // Readonly
+ ERC165Call(_, _)
+ | Name
+ | Symbol
+ | TotalSupply
+ | Decimals
+ | BalanceOf { .. }
+ | Allowance { .. } => None,
+
+ Transfer { .. } => {
+ let RefungibleTokenHandle(handle, token_id) = token;
+ let token_id = token_id.try_into().ok()?;
+ withdraw_transfer::<T>(&handle, &who, &token_id)
+ }
+ TransferFrom { from, .. } => {
+ let RefungibleTokenHandle(handle, token_id) = token;
+ let token_id = token_id.try_into().ok()?;
+ let from = T::CrossAccountId::from_eth(from);
+ withdraw_transfer::<T>(&handle, &from, &token_id)
+ }
+ Approve { .. } => {
+ let RefungibleTokenHandle(handle, token_id) = token;
+ let token_id = token_id.try_into().ok()?;
+ withdraw_approve::<T>(&handle, who.as_sub(), &token_id)
+ }
+ }
+ }
+
+ pub fn unique_extensions_call_sponsor<T>(
+ call: ERC20UniqueExtensionsCall<T>,
+ token: RefungibleTokenHandle<T>,
+ who: &T::CrossAccountId,
+ ) -> Option<()>
+ where
+ T: UniqueConfig + FungibleConfig + NonfungibleConfig + RefungibleConfig,
+ {
+ use ERC20UniqueExtensionsCall::*;
+
+ match call {
+ // Readonly
+ ERC165Call(_, _) => None,
+
+ // Not sponsored
+ BurnFrom { .. } | BurnFromCross { .. } | Repartition { .. } => None,
+
+ TransferCross { .. } | TransferFromCross { .. } => {
+ let RefungibleTokenHandle(handle, token_id) = token;
+ let token_id = token_id.try_into().ok()?;
+ withdraw_transfer::<T>(&handle, &who, &token_id)
+ }
+
+ ApproveCross { .. } => {
+ let RefungibleTokenHandle(handle, token_id) = token;
+ let token_id = token_id.try_into().ok()?;
+ withdraw_approve::<T>(&handle, who.as_sub(), &token_id)
+ }
+ }
+ }
+}
+
+mod erc1633 {
+ use super::*;
+
+ pub fn call_sponsor<T>(
+ call: ERC1633Call<T>,
+ _token: RefungibleTokenHandle<T>,
+ _who: &T::CrossAccountId,
+ ) -> Option<()>
+ where
+ T: UniqueConfig + FungibleConfig + NonfungibleConfig + RefungibleConfig,
+ {
+ use ERC1633Call::*;
+
+ match call {
+ // Readonly
+ ERC165Call(_, _) | ParentToken | ParentTokenId => None,
+ }
+ }
+}
runtime/common/runtime_apis.rsdiffbeforeafterboth--- a/runtime/common/runtime_apis.rs
+++ b/runtime/common/runtime_apis.rs
@@ -780,15 +780,16 @@
#[cfg(feature = "try-runtime")]
impl frame_try_runtime::TryRuntime<Block> for Runtime {
- fn on_runtime_upgrade() -> (frame_support::pallet_prelude::Weight, frame_support::pallet_prelude::Weight) {
+ fn on_runtime_upgrade(checks: bool) -> (frame_support::pallet_prelude::Weight, frame_support::pallet_prelude::Weight) {
log::info!("try-runtime::on_runtime_upgrade unique-chain.");
- let weight = Executive::try_runtime_upgrade().unwrap();
+ let weight = Executive::try_runtime_upgrade(checks).unwrap();
(weight, crate::config::substrate::RuntimeBlockWeights::get().max_block)
}
fn execute_block(
block: Block,
state_root_check: bool,
+ signature_check: bool,
select: frame_try_runtime::TryStateSelect
) -> frame_support::pallet_prelude::Weight {
log::info!(
@@ -799,7 +800,7 @@
select,
);
- Executive::try_execute_block(block, state_root_check, select).unwrap()
+ Executive::try_execute_block(block, state_root_check, signature_check, select).unwrap()
}
}
}
runtime/opal/Cargo.tomldiffbeforeafterboth--- a/runtime/opal/Cargo.toml
+++ b/runtime/opal/Cargo.toml
@@ -91,6 +91,7 @@
'pallet-unique-scheduler-v2/try-runtime',
'pallet-maintenance/try-runtime',
'pallet-test-utils?/try-runtime',
+ 'fp-self-contained/try-runtime',
]
std = [
'codec/std',
runtime/quartz/Cargo.tomldiffbeforeafterboth--- a/runtime/quartz/Cargo.toml
+++ b/runtime/quartz/Cargo.toml
@@ -86,6 +86,7 @@
'pallet-evm-transaction-payment/try-runtime',
'pallet-evm-migration/try-runtime',
'pallet-maintenance/try-runtime',
+ 'fp-self-contained/try-runtime',
]
std = [
'codec/std',
runtime/unique/Cargo.tomldiffbeforeafterboth--- a/runtime/unique/Cargo.toml
+++ b/runtime/unique/Cargo.toml
@@ -87,6 +87,7 @@
'pallet-evm-transaction-payment/try-runtime',
'pallet-evm-migration/try-runtime',
'pallet-maintenance/try-runtime',
+ 'fp-self-contained/try-runtime',
]
std = [
'codec/std',
tests/.eslintrc.jsondiffbeforeafterboth--- a/tests/.eslintrc.json
+++ b/tests/.eslintrc.json
@@ -18,6 +18,9 @@
"mocha"
],
"rules": {
+ "@typescript-eslint/no-floating-promises": [
+ "error"
+ ],
"indent": [
"error",
2,
tests/package.jsondiffbeforeafterboth--- a/tests/package.json
+++ b/tests/package.json
@@ -11,8 +11,8 @@
"@types/chai-subset": "^1.3.3",
"@types/mocha": "^10.0.0",
"@types/node": "^18.11.2",
- "@typescript-eslint/eslint-plugin": "^5.40.1",
- "@typescript-eslint/parser": "^5.40.1",
+ "@typescript-eslint/eslint-plugin": "^5.47.0",
+ "@typescript-eslint/parser": "^5.47.0",
"chai": "^4.3.6",
"chai-subset": "^1.6.0",
"eslint": "^8.25.0",
tests/src/apiConsts.test.tsdiffbeforeafterboth--- a/tests/src/apiConsts.test.ts
+++ b/tests/src/apiConsts.test.ts
@@ -46,33 +46,33 @@
describe('integration test: API UNIQUE consts', () => {
let api: ApiPromise;
-
+
before(async () => {
await usingPlaygrounds(async (helper) => {
api = await helper.getApi();
});
});
-
+
itSub('DEFAULT_NFT_COLLECTION_LIMITS', () => {
expect(api.consts.unique.nftDefaultCollectionLimits.toHuman()).to.deep.equal(DEFAULT_COLLETCTION_LIMIT);
});
-
+
itSub('DEFAULT_RFT_COLLECTION_LIMITS', () => {
expect(api.consts.unique.rftDefaultCollectionLimits.toHuman()).to.deep.equal(DEFAULT_COLLETCTION_LIMIT);
});
-
+
itSub('DEFAULT_FT_COLLECTION_LIMITS', () => {
expect(api.consts.unique.ftDefaultCollectionLimits.toHuman()).to.deep.equal(DEFAULT_COLLETCTION_LIMIT);
});
-
+
itSub('MAX_COLLECTION_NAME_LENGTH', () => {
checkConst(api.consts.unique.maxCollectionNameLength, MAX_COLLECTION_NAME_LENGTH);
});
-
+
itSub('MAX_COLLECTION_DESCRIPTION_LENGTH', () => {
checkConst(api.consts.unique.maxCollectionDescriptionLength, MAX_COLLECTION_DESCRIPTION_LENGTH);
});
-
+
itSub('MAX_COLLECTION_PROPERTIES_SIZE', () => {
checkConst(api.consts.unique.maxCollectionPropertiesSize, MAX_COLLECTION_PROPERTIES_SIZE);
});
@@ -84,31 +84,31 @@
itSub('MAX_PROPERTY_KEY_LENGTH', () => {
checkConst(api.consts.unique.maxPropertyKeyLength, MAX_PROPERTY_KEY_LENGTH);
});
-
+
itSub('MAX_PROPERTY_VALUE_LENGTH', () => {
checkConst(api.consts.unique.maxPropertyValueLength, MAX_PROPERTY_VALUE_LENGTH);
});
-
+
itSub('MAX_PROPERTIES_PER_ITEM', () => {
checkConst(api.consts.unique.maxPropertiesPerItem, MAX_PROPERTIES_PER_ITEM);
});
-
+
itSub('NESTING_BUDGET', () => {
checkConst(api.consts.unique.nestingBudget, NESTING_BUDGET);
});
-
+
itSub('MAX_TOKEN_PROPERTIES_SIZE', () => {
checkConst(api.consts.unique.maxTokenPropertiesSize, MAX_TOKEN_PROPERTIES_SIZE);
});
-
+
itSub('COLLECTION_ADMINS_LIMIT', () => {
checkConst(api.consts.unique.collectionAdminsLimit, COLLECTION_ADMINS_LIMIT);
});
-
+
itSub('HELPERS_CONTRACT_ADDRESS', () => {
expect(api.consts.evmContractHelpers.contractAddress.toString().toLowerCase()).to.be.equal(HELPERS_CONTRACT_ADDRESS.toLowerCase());
});
-
+
itSub('EVM_COLLECTION_HELPERS_ADDRESS', () => {
expect(api.consts.common.contractAddress.toString().toLowerCase()).to.be.equal(EVM_COLLECTION_HELPERS_ADDRESS.toLowerCase());
});
tests/src/app-promotion.seqtest.tsdiffbeforeafterboth--- a/tests/src/app-promotion.seqtest.ts
+++ b/tests/src/app-promotion.seqtest.ts
@@ -50,31 +50,31 @@
await expect(helper.signTransaction(nonAdmin, api.tx.appPromotion.setAdminAddress({Substrate: nonAdmin.address}))).to.be.rejected;
await expect(helper.signTransaction(nonAdmin, api.tx.sudo.sudo(api.tx.appPromotion.setAdminAddress({Substrate: nonAdmin.address})))).to.be.rejected;
});
-
+
itSub('can be any valid CrossAccountId', async ({helper}) => {
// We are not going to set an eth address as a sponsor,
// but we do want to check, it doesn't break anything;
const api = helper.getApi();
const [account] = await helper.arrange.createAccounts([10n], donor);
- const ethAccount = helper.address.substrateToEth(account.address);
+ const ethAccount = helper.address.substrateToEth(account.address);
// Alice sets Ethereum address as a sudo. Then Substrate address back...
await expect(helper.signTransaction(superuser, api.tx.sudo.sudo(api.tx.appPromotion.setAdminAddress({Ethereum: ethAccount})))).to.be.fulfilled;
await expect(helper.signTransaction(superuser, api.tx.sudo.sudo(api.tx.appPromotion.setAdminAddress({Substrate: palletAdmin.address})))).to.be.fulfilled;
-
+
// ...It doesn't break anything;
const collection = await helper.nft.mintCollection(account, {name: 'New', description: 'New Collection', tokenPrefix: 'Promotion'});
await expect(helper.signTransaction(account, api.tx.appPromotion.sponsorCollection(collection.collectionId))).to.be.rejected;
});
-
+
itSub('can be reassigned', async ({helper}) => {
const api = helper.getApi();
const [oldAdmin, newAdmin, collectionOwner] = await helper.arrange.createAccounts([10n, 10n, 10n], donor);
const collection = await helper.nft.mintCollection(collectionOwner, {name: 'New', description: 'New Collection', tokenPrefix: 'Promotion'});
-
+
await expect(helper.signTransaction(superuser, api.tx.sudo.sudo(api.tx.appPromotion.setAdminAddress({Substrate: oldAdmin.address})))).to.be.fulfilled;
await expect(helper.signTransaction(superuser, api.tx.sudo.sudo(api.tx.appPromotion.setAdminAddress({Substrate: newAdmin.address})))).to.be.fulfilled;
await expect(helper.signTransaction(oldAdmin, api.tx.appPromotion.sponsorCollection(collection.collectionId))).to.be.rejected;
-
+
await expect(helper.signTransaction(newAdmin, api.tx.appPromotion.sponsorCollection(collection.collectionId))).to.be.fulfilled;
});
});
tests/src/approve.test.tsdiffbeforeafterboth--- a/tests/src/approve.test.ts
+++ b/tests/src/approve.test.ts
@@ -538,7 +538,7 @@
const approveTx = () => helper.rft.approveToken(alice, collectionId, 1, {Substrate: bob.address});
await expect(approveTx()).to.be.rejected;
});
-
+
itSub('[nft] Approve transfer of a token that does not exist', async ({helper}) => {
const {collectionId} = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});
const approveTx = () => helper.nft.approveToken(alice, collectionId, 2, {Substrate: bob.address});
@@ -639,7 +639,7 @@
await helper.rft.setAllowanceForAll(alice, collectionId, {Substrate: bob.address}, true);
const checkAfterApproval = await helper.rft.allowanceForAll(collectionId, {Substrate: alice.address}, {Substrate: bob.address});
expect(checkAfterApproval).to.be.true;
-
+
await helper.rft.setAllowanceForAll(alice, collectionId, {Substrate: bob.address}, false);
const checkAfterDisapproval = await helper.rft.allowanceForAll(collectionId, {Substrate: alice.address}, {Substrate: bob.address});
expect(checkAfterDisapproval).to.be.false;
tests/src/burnItem.test.tsdiffbeforeafterboth--- a/tests/src/burnItem.test.ts
+++ b/tests/src/burnItem.test.ts
@@ -185,7 +185,7 @@
const collection = await helper.nft.mintCollection(alice, {name: 'Coll', description: 'Desc', tokenPrefix: 'T'});
const tokenAlice = await collection.mintToken(alice, {Substrate: alice.address});
const tokenBob = await collection.mintToken(alice, {Substrate: bob.address});
-
+
// 1. Zero burn of own tokens allowed:
await helper.executeExtrinsic(alice, 'api.tx.unique.burnItem', [collection.collectionId, tokenAlice.tokenId, 0]);
// 2. Zero burn of non-owned tokens not allowed:
tests/src/calibrate.tsdiffbeforeafterboth--- a/tests/src/calibrate.ts
+++ b/tests/src/calibrate.ts
@@ -295,6 +295,7 @@
}
}
+// eslint-disable-next-line @typescript-eslint/no-floating-promises
(async () => {
await usingEthPlaygrounds(async (helper: EthUniqueHelper, privateKey) => {
// Subsequent runs reduce error, as price line is not actually straight, this is a curve
tests/src/createCollection.test.tsdiffbeforeafterboth--- a/tests/src/createCollection.test.ts
+++ b/tests/src/createCollection.test.ts
@@ -127,7 +127,7 @@
const mintCollectionTx = () => helper.nft.mintCollection(alice, {name: 'name', description: 'descr', tokenPrefix: 'A'.repeat(17)});
await expect(mintCollectionTx()).to.be.rejectedWith('Verification Error');
});
-
+
itSub('(!negative test!) fails when bad limits are set', async ({helper}) => {
const mintCollectionTx = () => helper.nft.mintCollection(alice, {name: 'name', description: 'descr', tokenPrefix: 'COL', limits: {tokenLimit: 0}});
await expect(mintCollectionTx()).to.be.rejectedWith(/common\.CollectionTokenLimitExceeded/);
tests/src/createMultipleItems.test.tsdiffbeforeafterboth--- a/tests/src/createMultipleItems.test.ts
+++ b/tests/src/createMultipleItems.test.ts
@@ -272,8 +272,8 @@
const types = ['NFT', 'Fungible', 'ReFungible'];
await expect(helper.executeExtrinsic(
- alice,
- 'api.tx.unique.createMultipleItems',
+ alice,
+ 'api.tx.unique.createMultipleItems',
[collectionId, {Substrate: alice.address}, types],
)).to.be.rejectedWith(/nonfungible\.NotNonfungibleDataUsedToMintFungibleCollectionToken/);
});
tests/src/eth/abi/reFungibleDeprecated.jsondiffbeforeafterboth--- a/tests/src/eth/abi/reFungibleDeprecated.json
+++ b/tests/src/eth/abi/reFungibleDeprecated.json
@@ -98,5 +98,33 @@
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
+ },
+ {
+ "inputs": [
+ { "internalType": "address", "name": "to", "type": "address" },
+ { "internalType": "uint256[]", "name": "tokenIds", "type": "uint256[]" }
+ ],
+ "name": "mintBulk",
+ "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ { "internalType": "address", "name": "to", "type": "address" },
+ {
+ "components": [
+ { "internalType": "uint256", "name": "field_0", "type": "uint256" },
+ { "internalType": "string", "name": "field_1", "type": "string" }
+ ],
+ "internalType": "struct Tuple0[]",
+ "name": "tokens",
+ "type": "tuple[]"
+ }
+ ],
+ "name": "mintBulkWithTokenURI",
+ "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],
+ "stateMutability": "nonpayable",
+ "type": "function"
}
]
tests/src/eth/api/ContractHelpers.soldiffbeforeafterboth--- a/tests/src/eth/api/ContractHelpers.sol
+++ b/tests/src/eth/api/ContractHelpers.sol
@@ -183,7 +183,9 @@
/// Ethereum representation of Optional value with CrossAddress.
struct OptionCrossAddress {
+ /// TODO: field description
bool status;
+ /// TODO: field description
CrossAddress value;
}
tests/src/eth/collectionSponsoring.test.tsdiffbeforeafterboth--- a/tests/src/eth/collectionSponsoring.test.ts
+++ b/tests/src/eth/collectionSponsoring.test.ts
@@ -15,10 +15,10 @@
// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
import {IKeyringPair} from '@polkadot/types/types';
-import {usingPlaygrounds} from '../util/index';
+import {Pallets, requirePalletsOrSkip, usingPlaygrounds} from '../util/index';
import {itEth, expect} from './util';
-describe('evm collection sponsoring', () => {
+describe('evm nft collection sponsoring', () => {
let donor: IKeyringPair;
let alice: IKeyringPair;
let nominal: bigint;
@@ -101,12 +101,14 @@
expect(await collectionEvm.methods.hasCollectionPendingSponsor().call({from: owner})).to.be.true;
await collectionEvm.methods.confirmCollectionSponsorship().send({from: sponsor});
+ let sponsorStruct = await collectionEvm.methods.collectionSponsor().call({from: owner});
+ expect(helper.address.restoreCrossAccountFromBigInt(BigInt(sponsorStruct.sub))).to.be.eq(helper.address.ethToSubstrate(sponsor, true));
expect(await collectionEvm.methods.hasCollectionPendingSponsor().call({from: owner})).to.be.false;
await collectionEvm.methods.removeCollectionSponsor().send({from: owner});
- const sponsorTuple = await collectionEvm.methods.collectionSponsor().call({from: owner});
- expect(sponsorTuple.eth).to.be.eq('0x0000000000000000000000000000000000000000');
+ sponsorStruct = await collectionEvm.methods.collectionSponsor().call({from: owner});
+ expect(sponsorStruct.eth).to.be.eq('0x0000000000000000000000000000000000000000');
}));
[
@@ -142,7 +144,7 @@
expect(nextTokenId).to.be.equal('1');
// Set collection permissions:
- const oldPermissions = (await collectionSub.getData())!.raw.permissions; // (await getDetailedCollectionInfo(api, collectionId))!.permissions.toHuman();
+ const oldPermissions = (await collectionSub.getData())!.raw.permissions;
expect(oldPermissions.mintMode).to.be.false;
expect(oldPermissions.access).to.be.equal('Normal');
@@ -150,12 +152,13 @@
await collectionEvm.methods.addToCollectionAllowListCross(userCross).send({from: owner});
await collectionEvm.methods.setCollectionMintMode(true).send({from: owner});
- const newPermissions = (await collectionSub.getData())!.raw.permissions; // (await getDetailedCollectionInfo(api, collectionId))!.permissions.toHuman();
+ const newPermissions = (await collectionSub.getData())!.raw.permissions;
expect(newPermissions.mintMode).to.be.true;
expect(newPermissions.access).to.be.equal('AllowList');
const ownerBalanceBefore = await helper.balance.getSubstrate(helper.address.ethToSubstrate(owner));
const sponsorBalanceBefore = await helper.balance.getSubstrate(helper.address.ethToSubstrate(sponsorEth));
+ const userBalanceBefore = await helper.balance.getSubstrate(helper.address.ethToSubstrate(user));
// User can mint token without balance:
{
@@ -179,7 +182,7 @@
expect(await collectionEvm.methods.tokenURI(nextTokenId).call()).to.be.equal('Test URI');
expect(ownerBalanceBefore).to.be.eq(ownerBalanceAfter);
- expect(userBalanceAfter).to.be.eq(0n);
+ expect(userBalanceAfter).to.be.eq(userBalanceBefore);
expect(sponsorBalanceBefore > sponsorBalanceAfter).to.be.true;
}
}));
@@ -315,3 +318,531 @@
expect(collectionSponsor).to.deep.eq({Unconfirmed: sponsorSub.address});
});
});
+
+describe('evm RFT collection sponsoring', () => {
+ let donor: IKeyringPair;
+ let alice: IKeyringPair;
+ let nominal: bigint;
+
+ before(async function() {
+ await usingPlaygrounds(async (helper, privateKey) => {
+ requirePalletsOrSkip(this, helper, [Pallets.ReFungible]);
+ donor = await privateKey({filename: __filename});
+ [alice] = await helper.arrange.createAccounts([100n], donor);
+ nominal = helper.balance.getOneTokenNominal();
+ });
+ });
+
+ [
+ 'mintCross',
+ 'mintWithTokenURI',
+ ].map(testCase =>
+ itEth(`[${testCase}] sponsors mint transactions`, async ({helper}) => {
+ const collection = await helper.rft.mintCollection(alice, {tokenPrefix: 'spnr', permissions: {mintMode: true}, tokenPropertyPermissions: [
+ {key: 'URI', permission: {tokenOwner: true, mutable: true, collectionAdmin: true}},
+ ]});
+
+ const owner = await helper.eth.createAccountWithBalance(donor);
+ await collection.setSponsor(alice, alice.address);
+ await collection.confirmSponsorship(alice);
+
+ const minter = helper.eth.createAccount();
+ const minterCross = helper.ethCrossAccount.fromAddress(minter);
+ expect(await helper.balance.getEthereum(minter)).to.equal(0n);
+
+ const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId);
+ const contract = await helper.ethNativeContract.collection(collectionAddress, 'rft', minter, true);
+
+ await collection.addToAllowList(alice, {Ethereum: minter});
+ await collection.addAdmin(alice, {Ethereum: owner});
+ const collectionHelpers = await helper.ethNativeContract.collectionHelpers(owner);
+ await collectionHelpers.methods.makeCollectionERC721MetadataCompatible(collectionAddress, 'base/')
+ .send();
+
+ let mintingResult;
+ let tokenId;
+ switch (testCase) {
+ case 'mintCross':
+ mintingResult = await contract.methods.mintCross(minterCross, []).send();
+ break;
+ case 'mintWithTokenURI':
+ mintingResult = await contract.methods.mintWithTokenURI(minter, 'Test URI').send();
+ tokenId = mintingResult.events.Transfer.returnValues.tokenId;
+ expect(await contract.methods.tokenURI(tokenId).call()).to.be.equal('Test URI');
+ break;
+ }
+
+ const events = helper.eth.normalizeEvents(mintingResult.events);
+ expect(events).to.deep.include({
+ address: collectionAddress,
+ event: 'Transfer',
+ args: {
+ from: '0x0000000000000000000000000000000000000000',
+ to: minter,
+ tokenId: '1',
+ },
+ });
+ }));
+
+ [
+ 'setCollectionSponsorCross',
+ 'setCollectionSponsor', // Soft-deprecated
+ ].map(testCase =>
+ itEth(`[${testCase}] can remove collection sponsor`, async ({helper}) => {
+ const owner = await helper.eth.createAccountWithBalance(donor);
+ const collectionHelpers = await helper.ethNativeContract.collectionHelpers(owner);
+
+ let result = await collectionHelpers.methods.createRFTCollection('Sponsor collection', '1', '1').send({value: Number(2n * nominal)});
+ const collectionIdAddress = helper.ethAddress.normalizeAddress(result.events.CollectionCreated.returnValues.collectionId);
+ const sponsor = await helper.eth.createAccountWithBalance(donor);
+ const sponsorCross = helper.ethCrossAccount.fromAddress(sponsor);
+ const collectionEvm = await helper.ethNativeContract.collection(collectionIdAddress, 'rft', owner, testCase === 'setCollectionSponsor');
+
+ expect(await collectionEvm.methods.hasCollectionPendingSponsor().call({from: owner})).to.be.false;
+ result = await collectionEvm.methods[testCase](testCase === 'setCollectionSponsor' ? sponsor : sponsorCross).send({from: owner});
+ expect(await collectionEvm.methods.hasCollectionPendingSponsor().call({from: owner})).to.be.true;
+
+ await collectionEvm.methods.confirmCollectionSponsorship().send({from: sponsor});
+ expect(await collectionEvm.methods.hasCollectionPendingSponsor().call({from: owner})).to.be.false;
+
+ await collectionEvm.methods.removeCollectionSponsor().send({from: owner});
+
+ const sponsorStruct = await collectionEvm.methods.collectionSponsor().call({from: owner});
+ expect(sponsorStruct.eth).to.be.eq('0x0000000000000000000000000000000000000000');
+ }));
+
+ [
+ 'setCollectionSponsorCross',
+ 'setCollectionSponsor', // Soft-deprecated
+ ].map(testCase =>
+ itEth(`[${testCase}] Can sponsor from evm address via access list`, async ({helper}) => {
+ const owner = await helper.eth.createAccountWithBalance(donor);
+ const sponsorEth = await helper.eth.createAccountWithBalance(donor);
+ const sponsorCrossEth = helper.ethCrossAccount.fromAddress(sponsorEth);
+
+ const {collectionId, collectionAddress} = await helper.eth.createERC721MetadataCompatibleRFTCollection(owner, 'Sponsor collection', '1', '1', '');
+
+ const collectionSub = helper.rft.getCollectionObject(collectionId);
+ const collectionEvm = await helper.ethNativeContract.collection(collectionAddress, 'rft', owner, testCase === 'setCollectionSponsor');
+
+ // Set collection sponsor:
+ await collectionEvm.methods[testCase](testCase === 'setCollectionSponsor' ? sponsorEth : sponsorCrossEth).send({from: owner});
+ let sponsorship = (await collectionSub.getData())!.raw.sponsorship;
+ expect(sponsorship.Unconfirmed).to.be.eq(helper.address.ethToSubstrate(sponsorEth, true));
+ // Account cannot confirm sponsorship if it is not set as a sponsor
+ await expect(collectionEvm.methods.confirmCollectionSponsorship().call()).to.be.rejectedWith('ConfirmSponsorshipFail');
+
+ // Sponsor can confirm sponsorship:
+ await collectionEvm.methods.confirmCollectionSponsorship().send({from: sponsorEth});
+ sponsorship = (await collectionSub.getData())!.raw.sponsorship;
+ expect(sponsorship.Confirmed).to.be.eq(helper.address.ethToSubstrate(sponsorEth, true));
+
+ // Create user with no balance:
+ const user = helper.eth.createAccount();
+ const userCross = helper.ethCrossAccount.fromAddress(user);
+ const nextTokenId = await collectionEvm.methods.nextTokenId().call();
+ expect(nextTokenId).to.be.equal('1');
+
+ // Set collection permissions:
+ const oldPermissions = (await collectionSub.getData())!.raw.permissions;
+ expect(oldPermissions.mintMode).to.be.false;
+ expect(oldPermissions.access).to.be.equal('Normal');
+
+ await collectionEvm.methods.setCollectionAccess(1 /*'AllowList'*/).send({from: owner});
+ await collectionEvm.methods.addToCollectionAllowListCross(userCross).send({from: owner});
+ await collectionEvm.methods.setCollectionMintMode(true).send({from: owner});
+
+ const newPermissions = (await collectionSub.getData())!.raw.permissions;
+ expect(newPermissions.mintMode).to.be.true;
+ expect(newPermissions.access).to.be.equal('AllowList');
+
+ const ownerBalanceBefore = await helper.balance.getSubstrate(helper.address.ethToSubstrate(owner));
+ const sponsorBalanceBefore = await helper.balance.getSubstrate(helper.address.ethToSubstrate(sponsorEth));
+ const userBalanceBefore = await helper.balance.getSubstrate(helper.address.ethToSubstrate(user));
+
+ // User can mint token without balance:
+ {
+ const result = await collectionEvm.methods.mintWithTokenURI(user, 'Test URI').send({from: user});
+ const events = helper.eth.normalizeEvents(result.events);
+
+ expect(events).to.deep.include({
+ address: collectionAddress,
+ event: 'Transfer',
+ args: {
+ from: '0x0000000000000000000000000000000000000000',
+ to: user,
+ tokenId: '1',
+ },
+ });
+
+ const ownerBalanceAfter = await helper.balance.getSubstrate(helper.address.ethToSubstrate(owner));
+ const sponsorBalanceAfter = await helper.balance.getSubstrate(helper.address.ethToSubstrate(sponsorEth));
+ const userBalanceAfter = await helper.balance.getSubstrate(helper.address.ethToSubstrate(user));
+
+ expect(await collectionEvm.methods.tokenURI(nextTokenId).call()).to.be.equal('Test URI');
+ expect(ownerBalanceBefore).to.be.eq(ownerBalanceAfter);
+ expect(userBalanceAfter).to.be.eq(userBalanceBefore);
+ expect(sponsorBalanceBefore > sponsorBalanceAfter).to.be.true;
+ }
+ }));
+
+ [
+ 'setCollectionSponsorCross',
+ 'setCollectionSponsor', // Soft-deprecated
+ ].map(testCase =>
+ itEth(`[${testCase}] Check that collection admin EVM transaction spend money from sponsor eth address`, async ({helper}) => {
+ const owner = await helper.eth.createAccountWithBalance(donor);
+ const sponsor = await helper.eth.createAccountWithBalance(donor);
+ const sponsorCross = helper.ethCrossAccount.fromAddress(sponsor);
+
+ const {collectionAddress, collectionId} = await helper.eth.createERC721MetadataCompatibleRFTCollection(owner,'Sponsor collection', '1', '1', '');
+
+ const collectionSub = helper.rft.getCollectionObject(collectionId);
+ const collectionEvm = await helper.ethNativeContract.collection(collectionAddress, 'rft', owner, testCase === 'setCollectionSponsor');
+ // Set collection sponsor:
+ expect(await collectionEvm.methods.hasCollectionPendingSponsor().call()).to.be.false;
+ await collectionEvm.methods[testCase](testCase === 'setCollectionSponsor' ? sponsor : sponsorCross).send();
+ expect(await collectionEvm.methods.hasCollectionPendingSponsor().call()).to.be.true;
+ let collectionData = (await collectionSub.getData())!;
+ expect(collectionData.raw.sponsorship.Unconfirmed).to.be.eq(helper.address.ethToSubstrate(sponsor, true));
+ await expect(collectionEvm.methods.confirmCollectionSponsorship().call()).to.be.rejectedWith('ConfirmSponsorshipFail');
+ expect(await collectionEvm.methods.hasCollectionPendingSponsor().call()).to.be.true;
+
+ await collectionEvm.methods.confirmCollectionSponsorship().send({from: sponsor});
+ collectionData = (await collectionSub.getData())!;
+ expect(collectionData.raw.sponsorship.Confirmed).to.be.eq(helper.address.ethToSubstrate(sponsor, true));
+ expect(await collectionEvm.methods.hasCollectionPendingSponsor().call()).to.be.false;
+ const sponsorStruct = await collectionEvm.methods.collectionSponsor().call({from: owner});
+ const sponsorSubAddress = helper.address.normalizeSubstrateToChainFormat(helper.address.ethToSubstrate(sponsor));
+ const actualSubAddress = helper.address.normalizeSubstrateToChainFormat(helper.address.restoreCrossAccountFromBigInt(BigInt(sponsorStruct.sub)));
+ expect(actualSubAddress).to.be.equal(sponsorSubAddress);
+
+ const user = helper.eth.createAccount();
+ const userCross = helper.ethCrossAccount.fromAddress(user);
+ await collectionEvm.methods.addCollectionAdminCross(userCross).send();
+
+ const ownerBalanceBefore = await helper.balance.getSubstrate(helper.address.ethToSubstrate(owner));
+ const sponsorBalanceBefore = await helper.balance.getSubstrate(helper.address.ethToSubstrate(sponsor));
+
+ const mintingResult = await collectionEvm.methods.mintWithTokenURI(user, 'Test URI').send({from: user});
+ const tokenId = mintingResult.events.Transfer.returnValues.tokenId;
+
+ const events = helper.eth.normalizeEvents(mintingResult.events);
+ const address = helper.ethAddress.fromCollectionId(collectionId);
+
+ expect(events).to.deep.include({
+ address,
+ event: 'Transfer',
+ args: {
+ from: '0x0000000000000000000000000000000000000000',
+ to: user,
+ tokenId: '1',
+ },
+ });
+ expect(await collectionEvm.methods.tokenURI(tokenId).call({from: user})).to.be.equal('Test URI');
+
+ const ownerBalanceAfter = await helper.balance.getSubstrate(helper.address.ethToSubstrate(owner));
+ expect(ownerBalanceAfter).to.be.eq(ownerBalanceBefore);
+ const sponsorBalanceAfter = await helper.balance.getSubstrate(helper.address.ethToSubstrate(sponsor));
+ expect(sponsorBalanceAfter < sponsorBalanceBefore).to.be.true;
+ }));
+
+ itEth('Check that collection admin EVM transaction spend money from sponsor sub address', async ({helper}) => {
+ const owner = await helper.eth.createAccountWithBalance(donor);
+ const sponsor = alice;
+ const sponsorCross = helper.ethCrossAccount.fromKeyringPair(sponsor);
+
+ const {collectionAddress, collectionId} = await helper.eth.createERC721MetadataCompatibleRFTCollection(owner,'Sponsor collection', '1', '1', '');
+
+ const collectionSub = helper.rft.getCollectionObject(collectionId);
+ const collectionEvm = await helper.ethNativeContract.collection(collectionAddress, 'rft', owner, false);
+ // Set collection sponsor:
+ expect(await collectionEvm.methods.hasCollectionPendingSponsor().call()).to.be.false;
+ await collectionEvm.methods.setCollectionSponsorCross(sponsorCross).send();
+ expect(await collectionEvm.methods.hasCollectionPendingSponsor().call()).to.be.true;
+ let collectionData = (await collectionSub.getData())!;
+ expect(collectionData.raw.sponsorship.Unconfirmed).to.be.eq(sponsor.address);
+ await expect(collectionEvm.methods.confirmCollectionSponsorship().call()).to.be.rejectedWith('ConfirmSponsorshipFail');
+
+ await collectionSub.confirmSponsorship(sponsor);
+ collectionData = (await collectionSub.getData())!;
+ expect(collectionData.raw.sponsorship.Confirmed).to.be.eq(sponsor.address);
+ expect(await collectionEvm.methods.hasCollectionPendingSponsor().call()).to.be.false;
+ const sponsorStruct = await collectionEvm.methods.collectionSponsor().call({from: owner});
+ expect(BigInt(sponsorStruct.sub)).to.be.equal(BigInt('0x' + Buffer.from(sponsor.addressRaw).toString('hex')));
+
+ const user = helper.eth.createAccount();
+ const userCross = helper.ethCrossAccount.fromAddress(user);
+ await collectionEvm.methods.addCollectionAdminCross(userCross).send();
+
+ const ownerBalanceBefore = await helper.balance.getSubstrate(helper.address.ethToSubstrate(owner));
+ const sponsorBalanceBefore = await helper.balance.getSubstrate(sponsor.address);
+
+ const mintingResult = await collectionEvm.methods.mintWithTokenURI(user, 'Test URI').send({from: user});
+ const tokenId = mintingResult.events.Transfer.returnValues.tokenId;
+
+ const events = helper.eth.normalizeEvents(mintingResult.events);
+
+ expect(events).to.deep.include({
+ address: collectionAddress,
+ event: 'Transfer',
+ args: {
+ from: '0x0000000000000000000000000000000000000000',
+ to: user,
+ tokenId: '1',
+ },
+ });
+ expect(await collectionEvm.methods.tokenURI(tokenId).call({from: user})).to.be.equal('Test URI');
+
+ const ownerBalanceAfter = await helper.balance.getSubstrate(helper.address.ethToSubstrate(owner));
+ expect(ownerBalanceAfter).to.be.eq(ownerBalanceBefore);
+ const sponsorBalanceAfter = await helper.balance.getSubstrate(sponsor.address);
+ expect(sponsorBalanceAfter < sponsorBalanceBefore).to.be.true;
+ });
+
+ itEth('Sponsoring collection from substrate address via access list', async ({helper}) => {
+ const owner = await helper.eth.createAccountWithBalance(donor);
+ const user = helper.eth.createAccount();
+ const userCross = helper.ethCrossAccount.fromAddress(user);
+ const sponsor = alice;
+ const sponsorCross = helper.ethCrossAccount.fromKeyringPair(sponsor);
+
+ const {collectionAddress, collectionId} = await helper.eth.createERC721MetadataCompatibleRFTCollection(owner,'Sponsor collection', '1', '1', '');
+ const collectionEvm = await helper.ethNativeContract.collection(collectionAddress, 'rft', owner, false);
+
+ await collectionEvm.methods.setCollectionSponsorCross(sponsorCross).send({from: owner});
+
+ const collectionSub = helper.rft.getCollectionObject(collectionId);
+ await collectionSub.confirmSponsorship(sponsor);
+
+ const nextTokenId = await collectionEvm.methods.nextTokenId().call();
+ expect(nextTokenId).to.be.equal('1');
+
+ await collectionEvm.methods.setCollectionAccess(1 /*'AllowList'*/).send({from: owner});
+
+ await collectionEvm.methods.addToCollectionAllowListCross(userCross).send({from: owner});
+ await collectionEvm.methods.setCollectionMintMode(true).send({from: owner});
+
+ const ownerBalanceBefore = await helper.balance.getSubstrate(helper.address.ethToSubstrate(owner));
+ const sponsorBalanceBefore = await helper.balance.getSubstrate(sponsor.address);
+ const userBalanceBefore = await helper.balance.getSubstrate(helper.address.ethToSubstrate(user));
+
+ {
+ const nextTokenId = await collectionEvm.methods.nextTokenId().call();
+ expect(nextTokenId).to.be.equal('1');
+ const mintingResult = await collectionEvm.methods.mintWithTokenURI(
+ user,
+ 'Test URI',
+ ).send({from: user});
+
+ const events = helper.eth.normalizeEvents(mintingResult.events);
+
+
+ expect(events).to.deep.include({
+ address: collectionAddress,
+ event: 'Transfer',
+ args: {
+ from: '0x0000000000000000000000000000000000000000',
+ to: user,
+ tokenId: nextTokenId,
+ },
+ });
+
+ const ownerBalanceAfter = await helper.balance.getSubstrate(helper.address.ethToSubstrate(owner));
+ const sponsorBalanceAfter = await helper.balance.getSubstrate(sponsor.address);
+ const userBalanceAfter = await helper.balance.getSubstrate(helper.address.ethToSubstrate(user));
+
+ expect(await collectionEvm.methods.tokenURI(nextTokenId).call()).to.be.equal('Test URI');
+ expect(ownerBalanceBefore).to.be.eq(ownerBalanceAfter);
+ expect(userBalanceAfter).to.be.eq(userBalanceBefore);
+ expect(sponsorBalanceBefore > sponsorBalanceAfter).to.be.true;
+ }
+ });
+
+ itEth('Can reassign collection sponsor', async ({helper}) => {
+ const owner = await helper.eth.createAccountWithBalance(donor);
+ const sponsorEth = await helper.eth.createAccountWithBalance(donor);
+ const sponsorCrossEth = helper.ethCrossAccount.fromAddress(sponsorEth);
+ const [sponsorSub] = await helper.arrange.createAccounts([100n], donor);
+ const sponsorCrossSub = helper.ethCrossAccount.fromKeyringPair(sponsorSub);
+
+ const {collectionAddress, collectionId} = await helper.eth.createERC721MetadataCompatibleRFTCollection(owner,'Sponsor collection', '1', '1', '');
+ const collectionSub = helper.rft.getCollectionObject(collectionId);
+ const collectionEvm = await helper.ethNativeContract.collection(collectionAddress, 'rft', owner);
+
+ // Set and confirm sponsor:
+ await collectionEvm.methods.setCollectionSponsorCross(sponsorCrossEth).send({from: owner});
+ await collectionEvm.methods.confirmCollectionSponsorship().send({from: sponsorEth});
+
+ // Can reassign sponsor:
+ await collectionEvm.methods.setCollectionSponsorCross(sponsorCrossSub).send({from: owner});
+ const collectionSponsor = (await collectionSub.getData())?.raw.sponsorship;
+ expect(collectionSponsor).to.deep.eq({Unconfirmed: sponsorSub.address});
+ });
+
+ [
+ 'transfer',
+ 'transferCross',
+ 'transferFrom',
+ 'transferFromCross',
+ ].map(testCase =>
+ itEth(`[${testCase}] Check that transfer via EVM spend money from sponsor address`, async ({helper}) => {
+ const owner = await helper.eth.createAccountWithBalance(donor);
+
+ const {collectionAddress} = await helper.eth.createERC721MetadataCompatibleRFTCollection(owner,'Sponsor collection', '1', '1', '');
+ const sponsor = await helper.eth.createAccountWithBalance(donor);
+ const sponsorCross = helper.ethCrossAccount.fromAddress(sponsor);
+ const receiver = await helper.eth.createAccountWithBalance(donor);
+ const collectionEvm = await helper.ethNativeContract.collection(collectionAddress, 'rft', owner);
+
+ await collectionEvm.methods.setCollectionSponsorCross(sponsorCross).send();
+ await collectionEvm.methods.confirmCollectionSponsorship().send({from: sponsor});
+
+ const user = await helper.eth.createAccountWithBalance(donor);
+ const userCross = helper.ethCrossAccount.fromAddress(user);
+ await collectionEvm.methods.addCollectionAdminCross(userCross).send();
+
+ const result = await collectionEvm.methods.mintWithTokenURI(user, 'Test URI').send({from: user});
+ const tokenId = result.events.Transfer.returnValues.tokenId;
+
+ const ownerBalanceBefore = await helper.balance.getSubstrate(helper.address.ethToSubstrate(owner));
+ const sponsorBalanceBefore = await helper.balance.getSubstrate(helper.address.ethToSubstrate(sponsor));
+ const userBalanceBefore = await helper.balance.getSubstrate(helper.address.ethToSubstrate(user));
+
+ switch (testCase) {
+ case 'transfer':
+ await collectionEvm.methods.transfer(receiver, tokenId).send({from: user});
+ break;
+ case 'transferCross':
+ await collectionEvm.methods.transferCross(helper.ethCrossAccount.fromAddress(receiver), tokenId).send({from: user});
+ break;
+ case 'transferFrom':
+ await collectionEvm.methods.transferFrom(user, receiver, tokenId).send({from: user});
+ break;
+ case 'transferFromCross':
+ await collectionEvm.methods.transferFromCross(helper.ethCrossAccount.fromAddress(user), helper.ethCrossAccount.fromAddress(receiver), tokenId).send({from: user});
+ break;
+ }
+
+ const ownerBalanceAfter = await helper.balance.getSubstrate(helper.address.ethToSubstrate(owner));
+ expect(ownerBalanceAfter).to.be.eq(ownerBalanceBefore);
+ const sponsorBalanceAfter = await helper.balance.getSubstrate(helper.address.ethToSubstrate(sponsor));
+ expect(sponsorBalanceAfter < sponsorBalanceBefore).to.be.true;
+ const userBalanceAfter = await helper.balance.getSubstrate(helper.address.ethToSubstrate(user));
+ expect(userBalanceAfter).to.be.eq(userBalanceBefore);
+ }));
+});
+
+describe('evm RFT token sponsoring', () => {
+ let donor: IKeyringPair;
+
+ before(async function() {
+ await usingPlaygrounds(async (helper, privateKey) => {
+ requirePalletsOrSkip(this, helper, [Pallets.ReFungible]);
+ donor = await privateKey({filename: __filename});
+ });
+ });
+
+ [
+ 'transfer',
+ 'transferCross',
+ 'transferFrom',
+ 'transferFromCross',
+ ].map(testCase =>
+ itEth(`[${testCase}] Check that token piece transfer via EVM spend money from sponsor address`, async ({helper}) => {
+ const owner = await helper.eth.createAccountWithBalance(donor);
+
+ const {collectionAddress, collectionId} = await helper.eth.createERC721MetadataCompatibleRFTCollection(owner,'Sponsor collection', '1', '1', '');
+ const sponsor = await helper.eth.createAccountWithBalance(donor);
+ const sponsorCross = helper.ethCrossAccount.fromAddress(sponsor);
+ const receiver = await helper.eth.createAccountWithBalance(donor);
+ const collectionEvm = await helper.ethNativeContract.collection(collectionAddress, 'rft', owner);
+
+ await collectionEvm.methods.setCollectionSponsorCross(sponsorCross).send();
+ await collectionEvm.methods.confirmCollectionSponsorship().send({from: sponsor});
+
+ const user = await helper.eth.createAccountWithBalance(donor);
+ const userCross = helper.ethCrossAccount.fromAddress(user);
+ await collectionEvm.methods.addCollectionAdminCross(userCross).send();
+
+ const result = await collectionEvm.methods.mintWithTokenURI(user, 'Test URI').send({from: user});
+ const tokenId = result.events.Transfer.returnValues.tokenId;
+
+ const tokenContract = await helper.ethNativeContract.rftTokenById(collectionId, tokenId, user);
+ await tokenContract.methods.repartition(2).send();
+
+ const ownerBalanceBefore = await helper.balance.getSubstrate(helper.address.ethToSubstrate(owner));
+ const sponsorBalanceBefore = await helper.balance.getSubstrate(helper.address.ethToSubstrate(sponsor));
+ const userBalanceBefore = await helper.balance.getSubstrate(helper.address.ethToSubstrate(user));
+
+ switch (testCase) {
+ case 'transfer':
+ await tokenContract.methods.transfer(receiver, 1).send();
+ break;
+ case 'transferCross':
+ await tokenContract.methods.transferCross(helper.ethCrossAccount.fromAddress(receiver), 1).send();
+ break;
+ case 'transferFrom':
+ await tokenContract.methods.transferFrom(user, receiver, 1).send();
+ break;
+ case 'transferFromCross':
+ await tokenContract.methods.transferFromCross(helper.ethCrossAccount.fromAddress(user), helper.ethCrossAccount.fromAddress(receiver), 1).send();
+ break;
+ }
+
+ const ownerBalanceAfter = await helper.balance.getSubstrate(helper.address.ethToSubstrate(owner));
+ expect(ownerBalanceAfter).to.be.eq(ownerBalanceBefore);
+ const sponsorBalanceAfter = await helper.balance.getSubstrate(helper.address.ethToSubstrate(sponsor));
+ expect(sponsorBalanceAfter < sponsorBalanceBefore).to.be.true;
+ const userBalanceAfter = await helper.balance.getSubstrate(helper.address.ethToSubstrate(user));
+ expect(userBalanceAfter).to.be.eq(userBalanceBefore);
+ }));
+
+ [
+ 'approve',
+ 'approveCross',
+ ].map(testCase =>
+ itEth(`[${testCase}] Check that approve via EVM spend money from sponsor address`, async ({helper}) => {
+ const owner = await helper.eth.createAccountWithBalance(donor);
+
+ const {collectionAddress, collectionId} = await helper.eth.createERC721MetadataCompatibleRFTCollection(owner,'Sponsor collection', '1', '1', '');
+ const sponsor = await helper.eth.createAccountWithBalance(donor);
+ const sponsorCross = helper.ethCrossAccount.fromAddress(sponsor);
+ const receiver = await helper.eth.createAccountWithBalance(donor);
+ const collectionEvm = await helper.ethNativeContract.collection(collectionAddress, 'rft', owner);
+
+ await collectionEvm.methods.setCollectionSponsorCross(sponsorCross).send();
+ await collectionEvm.methods.confirmCollectionSponsorship().send({from: sponsor});
+
+ const user = await helper.eth.createAccountWithBalance(donor);
+ const userCross = helper.ethCrossAccount.fromAddress(user);
+ await collectionEvm.methods.addCollectionAdminCross(userCross).send();
+
+ const result = await collectionEvm.methods.mintWithTokenURI(user, 'Test URI').send({from: user});
+ const tokenId = result.events.Transfer.returnValues.tokenId;
+
+ const tokenContract = await helper.ethNativeContract.rftTokenById(collectionId, tokenId, user);
+ await tokenContract.methods.repartition(2).send();
+
+ const ownerBalanceBefore = await helper.balance.getSubstrate(helper.address.ethToSubstrate(owner));
+ const sponsorBalanceBefore = await helper.balance.getSubstrate(helper.address.ethToSubstrate(sponsor));
+ const userBalanceBefore = await helper.balance.getSubstrate(helper.address.ethToSubstrate(user));
+
+ switch (testCase) {
+ case 'approve':
+ await tokenContract.methods.approve(receiver, 1).send();
+ break;
+ case 'approveCross':
+ await tokenContract.methods.approveCross(helper.ethCrossAccount.fromAddress(receiver), 1).send();
+ break;
+ }
+
+ const ownerBalanceAfter = await helper.balance.getSubstrate(helper.address.ethToSubstrate(owner));
+ expect(ownerBalanceAfter).to.be.eq(ownerBalanceBefore);
+ const sponsorBalanceAfter = await helper.balance.getSubstrate(helper.address.ethToSubstrate(sponsor));
+ expect(sponsorBalanceAfter < sponsorBalanceBefore).to.be.true;
+ const userBalanceAfter = await helper.balance.getSubstrate(helper.address.ethToSubstrate(user));
+ expect(userBalanceAfter).to.be.eq(userBalanceBefore);
+ }));
+});
+
tests/src/eth/createFTCollection.test.tsdiffbeforeafterboth--- a/tests/src/eth/createFTCollection.test.ts
+++ b/tests/src/eth/createFTCollection.test.ts
@@ -32,6 +32,7 @@
});
});
+ // TODO move sponsorship tests to another file:
// Soft-deprecated
itEth('[eth] Set sponsorship', async ({helper}) => {
const owner = await helper.eth.createAccountWithBalance(donor);
@@ -93,6 +94,11 @@
expect(await collectionHelpers
.methods.isCollectionExist(collectionAddress).call())
.to.be.true;
+
+ // check collectionOwner:
+ const collectionEvm = await helper.ethNativeContract.collection(collectionAddress, 'ft', owner, true);
+ const collectionOwner = await collectionEvm.methods.collectionOwner().call();
+ expect(helper.address.restoreCrossAccountFromBigInt(BigInt(collectionOwner.sub))).to.eq(helper.address.ethToSubstrate(owner, true));
});
itEth('destroyCollection', async ({helper}) => {
tests/src/eth/createNFTCollection.test.tsdiffbeforeafterboth--- a/tests/src/eth/createNFTCollection.test.ts
+++ b/tests/src/eth/createNFTCollection.test.ts
@@ -134,6 +134,11 @@
expect(await collectionHelpers
.methods.isCollectionExist(collectionAddress).call())
.to.be.true;
+
+ // check collectionOwner:
+ const collectionEvm = await helper.ethNativeContract.collection(collectionAddress, 'ft', owner, true);
+ const collectionOwner = await collectionEvm.methods.collectionOwner().call();
+ expect(helper.address.restoreCrossAccountFromBigInt(BigInt(collectionOwner.sub))).to.eq(helper.address.ethToSubstrate(owner, true));
});
});
tests/src/eth/createRFTCollection.test.tsdiffbeforeafterboth--- a/tests/src/eth/createRFTCollection.test.ts
+++ b/tests/src/eth/createRFTCollection.test.ts
@@ -88,27 +88,6 @@
]);
});
- // this test will occasionally fail when in async environment.
- itEth.skip('Check collection address exist', async ({helper}) => {
- const owner = await helper.eth.createAccountWithBalance(donor);
-
- const expectedCollectionId = +(await helper.callRpc('api.rpc.unique.collectionStats')).created + 1;
- const expectedCollectionAddress = helper.ethAddress.fromCollectionId(expectedCollectionId);
- const collectionHelpers = await helper.ethNativeContract.collectionHelpers(owner);
-
- expect(await collectionHelpers.methods
- .isCollectionExist(expectedCollectionAddress)
- .call()).to.be.false;
-
- await collectionHelpers.methods
- .createRFTCollection('A', 'A', 'A')
- .send({value: Number(2n * helper.balance.getOneTokenNominal())});
-
- expect(await collectionHelpers.methods
- .isCollectionExist(expectedCollectionAddress)
- .call()).to.be.true;
- });
-
// Soft-deprecated
itEth('[eth] Set sponsorship', async ({helper}) => {
const owner = await helper.eth.createAccountWithBalance(donor);
@@ -166,6 +145,11 @@
expect(await collectionHelpers
.methods.isCollectionExist(collectionAddress).call())
.to.be.true;
+
+ // check collectionOwner:
+ const collectionEvm = await helper.ethNativeContract.collection(collectionAddress, 'ft', owner, true);
+ const collectionOwner = await collectionEvm.methods.collectionOwner().call();
+ expect(helper.address.restoreCrossAccountFromBigInt(BigInt(collectionOwner.sub))).to.eq(helper.address.ethToSubstrate(owner, true));
});
});
tests/src/eth/evmCoder.test.tsdiffbeforeafterboth--- a/tests/src/eth/evmCoder.test.ts
+++ b/tests/src/eth/evmCoder.test.ts
@@ -62,7 +62,7 @@
donor = await privateKey({filename: __filename});
});
});
-
+
itEth('Call non-existing function', async ({helper}) => {
const owner = await helper.eth.createAccountWithBalance(donor);
const collection = await helper.eth.createNFTCollection(owner, 'EVMCODER', '', 'TEST');
tests/src/eth/nonFungible.test.tsdiffbeforeafterboth--- a/tests/src/eth/nonFungible.test.ts
+++ b/tests/src/eth/nonFungible.test.ts
@@ -167,7 +167,6 @@
expect(event.returnValues.to).to.be.equal(receiver);
expect(await contract.methods.tokenURI(tokenId).call()).to.be.equal('Test URI');
- console.log(await contract.methods.crossOwnerOf(tokenId).call());
expect(await contract.methods.crossOwnerOf(tokenId).call()).to.be.like([receiver, '0']);
// TODO: this wont work right now, need release 919000 first
// await helper.methods.setOffchainSchema(collectionIdAddress, 'https://offchain-service.local/token-info/{id}').send();
@@ -200,7 +199,6 @@
},
};
});
-
const collection = await helper.nft.mintCollection(minter, {
tokenPrefix: 'ethp',
tests/src/eth/proxyContract.test.tsdiffbeforeafterboth--- a/tests/src/eth/proxyContract.test.ts
+++ b/tests/src/eth/proxyContract.test.ts
@@ -31,11 +31,11 @@
const deployer = await helper.eth.createAccountWithBalance(donor);
const caller = await helper.eth.createAccountWithBalance(donor);
const proxyContract = await deployProxyContract(helper, deployer);
-
+
const realContractV1 = await deployRealContractV1(helper, deployer);
const realContractV1proxy = new helper.web3!.eth.Contract(realContractV1.options.jsonInterface, proxyContract.options.address, {from: caller, gas: helper.eth.DEFAULT_GAS});
await proxyContract.methods.updateVersion(realContractV1.options.address).send();
-
+
await realContractV1proxy.methods.flip().send();
await realContractV1proxy.methods.flip().send();
await realContractV1proxy.methods.flip().send();
tests/src/eth/scheduling.test.tsdiffbeforeafterboth--- a/tests/src/eth/scheduling.test.ts
+++ b/tests/src/eth/scheduling.test.ts
@@ -53,7 +53,7 @@
);
expect(await flipper.methods.getValue().call()).to.be.equal(initialValue);
-
+
await helper.wait.newBlocks(waitForBlocks + 1);
expect(await flipper.methods.getValue().call()).to.be.not.equal(initialValue);
tests/src/eth/util/index.tsdiffbeforeafterboth--- a/tests/src/eth/util/index.ts
+++ b/tests/src/eth/util/index.ts
@@ -58,9 +58,9 @@
silentConsole.disable();
}
};
-
+
export function itEth(name: string, cb: (apis: { helper: EthUniqueHelper, privateKey: (seed: string | {filename: string}) => Promise<IKeyringPair> }) => any, opts: { only?: boolean, skip?: boolean, requiredPallets?: string[] } = {}) {
- (opts.only ? it.only :
+ (opts.only ? it.only :
opts.skip ? it.skip : it)(name, async function() {
await usingEthPlaygrounds(async (helper, privateKey) => {
if (opts.requiredPallets) {
tests/src/fungible.test.tsdiffbeforeafterboth--- a/tests/src/fungible.test.ts
+++ b/tests/src/fungible.test.ts
@@ -43,7 +43,7 @@
expect(itemCountAfter).to.be.equal(defaultTokenId);
expect(aliceBalance).to.be.equal(U128_MAX);
});
-
+
itSub('RPC method tokenOnewrs for fungible collection and token', async ({helper}) => {
const ethAcc = {Ethereum: '0x67fb3503a61b284dc83fa96dceec4192db47dc7c'};
const facelessCrowd = (await helper.arrange.createAccounts(Array(7).fill(0n), donor)).map(keyring => {return {Substrate: keyring.address};});
@@ -54,22 +54,22 @@
await collection.transfer(alice, {Substrate: bob.address}, 1000n);
await collection.transfer(alice, ethAcc, 900n);
-
+
for (let i = 0; i < 7; i++) {
await collection.transfer(alice, facelessCrowd[i], 1n);
- }
+ }
const owners = await collection.getTop10Owners();
// What to expect
expect(owners).to.deep.include.members([{Substrate: alice.address}, ethAcc, {Substrate: bob.address}, ...facelessCrowd]);
expect(owners.length).to.be.equal(10);
-
+
const [eleven] = await helper.arrange.createAccounts([0n], donor);
expect(await collection.transfer(alice, {Substrate: eleven.address}, 10n)).to.be.true;
expect((await collection.getTop10Owners()).length).to.be.equal(10);
});
-
+
itSub('Transfer token', async ({helper}) => {
const ethAcc = {Ethereum: '0x67fb3503a61b284dc83fa96dceec4192db47dc7c'};
const collection = await helper.ft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'});
@@ -108,7 +108,7 @@
expect(await collection.doesTokenExist(0)).to.be.true;
expect(await collection.getBalance({Substrate: alice.address})).to.be.equal(1n);
});
-
+
itSub('Burn all tokens ', async ({helper}) => {
const collection = await helper.ft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'});
await collection.mint(alice, 500n);
@@ -127,7 +127,7 @@
await collection.mint(alice, 100n);
expect(await collection.getBalance({Substrate: alice.address})).to.be.equal(100n);
-
+
expect(await collection.approveTokens(alice, {Substrate: bob.address}, 60n)).to.be.true;
expect(await collection.getApprovedTokens({Substrate: alice.address}, {Substrate: bob.address})).to.be.equal(60n);
expect(await collection.getBalance({Substrate: bob.address})).to.be.equal(0n);
@@ -169,11 +169,11 @@
// 1. Alice cannot transfer more than 0 tokens if balance low:
await expect(collection.transfer(alice, {Substrate: charlie.address}, 1n)).to.be.rejectedWith('common.TokenValueTooLow');
await expect(collection.transfer(alice, {Substrate: charlie.address}, 100n)).to.be.rejectedWith('common.TokenValueTooLow');
-
+
// 2. Alice cannot transfer non-existing token:
await expect(nonExistingCollection.transfer(alice, {Substrate: charlie.address}, 0n)).to.be.rejectedWith('common.CollectionNotFound');
await expect(nonExistingCollection.transfer(alice, {Substrate: charlie.address}, 1n)).to.be.rejectedWith('common.CollectionNotFound');
-
+
// 3. Zero transfer allowed (EIP-20):
await collection.transfer(bob, {Substrate: charlie.address}, 0n);
// 3.1 even if the balance = 0
tests/src/inflation.seqtest.tsdiffbeforeafterboth--- a/tests/src/inflation.seqtest.ts
+++ b/tests/src/inflation.seqtest.ts
@@ -26,7 +26,7 @@
superuser = await privateKey('//Alice');
});
});
-
+
itSub('First year inflation is 10%', async ({helper}) => {
// Make sure non-sudo can't start inflation
const [bob] = await helper.arrange.createAccounts([10n], superuser);
tests/src/interfaces/unique/definitions.tsdiffbeforeafterboth--- a/tests/src/interfaces/unique/definitions.ts
+++ b/tests/src/interfaces/unique/definitions.ts
@@ -38,39 +38,39 @@
types: {},
rpc: {
accountTokens: fun(
- 'Get tokens owned by an account in a collection',
- [collectionParam, crossAccountParam()],
+ 'Get tokens owned by an account in a collection',
+ [collectionParam, crossAccountParam()],
'Vec<u32>',
),
collectionTokens: fun(
- 'Get tokens contained within a collection',
- [collectionParam],
+ 'Get tokens contained within a collection',
+ [collectionParam],
'Vec<u32>',
),
tokenExists: fun(
- 'Check if the token exists',
- [collectionParam, tokenParam],
+ 'Check if the token exists',
+ [collectionParam, tokenParam],
'bool',
),
tokenOwner: fun(
- 'Get the token owner',
- [collectionParam, tokenParam],
+ 'Get the token owner',
+ [collectionParam, tokenParam],
`Option<${CROSS_ACCOUNT_ID_TYPE}>`,
),
topmostTokenOwner: fun(
- 'Get the topmost token owner in the hierarchy of a possibly nested token',
- [collectionParam, tokenParam],
+ 'Get the topmost token owner in the hierarchy of a possibly nested token',
+ [collectionParam, tokenParam],
`Option<${CROSS_ACCOUNT_ID_TYPE}>`,
),
tokenOwners: fun(
- 'Returns 10 tokens owners in no particular order',
- [collectionParam, tokenParam],
+ 'Returns 10 tokens owners in no particular order',
+ [collectionParam, tokenParam],
`Vec<${CROSS_ACCOUNT_ID_TYPE}>`,
),
tokenChildren: fun(
- 'Get tokens nested directly into the token',
- [collectionParam, tokenParam],
+ 'Get tokens nested directly into the token',
+ [collectionParam, tokenParam],
'Vec<UpDataStructsTokenChild>',
),
@@ -91,13 +91,13 @@
),
constMetadata: fun(
- 'Get token constant metadata',
- [collectionParam, tokenParam],
+ 'Get token constant metadata',
+ [collectionParam, tokenParam],
'Vec<u8>',
),
variableMetadata: fun(
- 'Get token variable metadata',
- [collectionParam, tokenParam],
+ 'Get token variable metadata',
+ [collectionParam, tokenParam],
'Vec<u8>',
),
@@ -107,77 +107,77 @@
'UpDataStructsTokenData',
),
totalSupply: fun(
- 'Get the amount of distinctive tokens present in a collection',
- [collectionParam],
+ 'Get the amount of distinctive tokens present in a collection',
+ [collectionParam],
'u32',
),
accountBalance: fun(
- 'Get the amount of any user tokens owned by an account',
- [collectionParam, crossAccountParam()],
+ 'Get the amount of any user tokens owned by an account',
+ [collectionParam, crossAccountParam()],
'u32',
),
balance: fun(
- 'Get the amount of a specific token owned by an account',
- [collectionParam, crossAccountParam(), tokenParam],
+ 'Get the amount of a specific token owned by an account',
+ [collectionParam, crossAccountParam(), tokenParam],
'u128',
),
allowance: fun(
- 'Get the amount of currently possible sponsored transactions on a token for the fee to be taken off a sponsor',
- [collectionParam, crossAccountParam('sender'), crossAccountParam('spender'), tokenParam],
+ 'Get the amount of currently possible sponsored transactions on a token for the fee to be taken off a sponsor',
+ [collectionParam, crossAccountParam('sender'), crossAccountParam('spender'), tokenParam],
'u128',
),
adminlist: fun(
- 'Get the list of admin accounts of a collection',
- [collectionParam],
+ 'Get the list of admin accounts of a collection',
+ [collectionParam],
'Vec<PalletEvmAccountBasicCrossAccountIdRepr>',
),
allowlist: fun(
- 'Get the list of accounts allowed to operate within a collection',
- [collectionParam],
+ 'Get the list of accounts allowed to operate within a collection',
+ [collectionParam],
'Vec<PalletEvmAccountBasicCrossAccountIdRepr>',
),
allowed: fun(
- 'Check if a user is allowed to operate within a collection',
- [collectionParam, crossAccountParam()],
+ 'Check if a user is allowed to operate within a collection',
+ [collectionParam, crossAccountParam()],
'bool',
),
lastTokenId: fun(
- 'Get the last token ID created in a collection',
- [collectionParam],
+ 'Get the last token ID created in a collection',
+ [collectionParam],
'u32',
),
collectionById: fun(
- 'Get a collection by the specified ID',
- [collectionParam],
+ 'Get a collection by the specified ID',
+ [collectionParam],
'Option<UpDataStructsRpcCollection>',
),
collectionStats: fun(
- 'Get chain stats about collections',
- [],
+ 'Get chain stats about collections',
+ [],
'UpDataStructsCollectionStats',
),
nextSponsored: fun(
- 'Get the number of blocks until sponsoring a transaction is available',
- [collectionParam, crossAccountParam(), tokenParam],
+ 'Get the number of blocks until sponsoring a transaction is available',
+ [collectionParam, crossAccountParam(), tokenParam],
'Option<u64>',
),
effectiveCollectionLimits: fun(
- 'Get effective collection limits',
- [collectionParam],
+ 'Get effective collection limits',
+ [collectionParam],
'Option<UpDataStructsCollectionLimits>',
),
totalPieces: fun(
- 'Get the total amount of pieces of an RFT',
- [collectionParam, tokenParam],
+ 'Get the total amount of pieces of an RFT',
+ [collectionParam, tokenParam],
'Option<u128>',
),
allowanceForAll: fun(
- 'Tells whether the given `owner` approves the `operator`.',
- [collectionParam, crossAccountParam('owner'), crossAccountParam('operator')],
+ 'Tells whether the given `owner` approves the `operator`.',
+ [collectionParam, crossAccountParam('owner'), crossAccountParam('operator')],
'Option<bool>',
),
},
tests/src/limits.test.tsdiffbeforeafterboth--- a/tests/src/limits.test.ts
+++ b/tests/src/limits.test.ts
@@ -30,7 +30,7 @@
itSub.skip('Collection limits allow greater number than chain limits, chain limits are enforced', async ({helper}) => {
const collection = await helper.nft.mintCollection(alice, {});
await collection.setLimits(alice, {accountTokenOwnershipLimit: 20});
-
+
for(let i = 0; i < 10; i++){
await expect(collection.mintToken(alice)).to.be.not.rejected;
}
@@ -40,14 +40,14 @@
}
await collection.burn(alice);
});
-
+
itSub('Collection limits allow lower number than chain limits, collection limits are enforced', async ({helper}) => {
const collection = await helper.nft.mintCollection(alice, {});
await collection.setLimits(alice, {accountTokenOwnershipLimit: 1});
await collection.mintToken(alice);
await expect(collection.mintToken(alice)).to.be.rejectedWith(/common\.AccountTokenLimitExceeded/);
-
+
await collection.burnToken(alice, 1);
await expect(collection.burn(alice)).to.be.not.rejected;
});
@@ -68,7 +68,7 @@
itSub.skip('Collection limits allow greater number than chain limits, chain limits are enforced', async ({helper}) => {
const collection = await helper.rft.mintCollection(alice, {});
await collection.setLimits(alice, {accountTokenOwnershipLimit: 20});
-
+
for(let i = 0; i < 10; i++){
await expect(collection.mintToken(alice, 10n)).to.be.not.rejected;
}
@@ -85,7 +85,7 @@
await collection.mintToken(alice);
await expect(collection.mintToken(alice)).to.be.rejectedWith(/common\.AccountTokenLimitExceeded/);
-
+
await collection.burnToken(alice, 1);
await expect(collection.burn(alice)).to.be.not.rejected;
});
@@ -314,7 +314,7 @@
await collection.setSponsor(alice, alice.address);
await collection.confirmSponsorship(alice);
-
+
await token.transfer(alice, {Substrate: bob.address});
const aliceBalanceBefore = await helper.balance.getSubstrate(alice.address);
@@ -345,7 +345,7 @@
await collection.setSponsor(alice, alice.address);
await collection.confirmSponsorship(alice);
-
+
await collection.transfer(alice, {Substrate: bob.address}, 2n);
const aliceBalanceBefore = await helper.balance.getSubstrate(alice.address);
@@ -387,7 +387,7 @@
await collection.setSponsor(alice, alice.address);
await collection.confirmSponsorship(alice);
-
+
await token.transfer(alice, {Substrate: bob.address}, 2n);
const aliceBalanceBefore = await helper.balance.getSubstrate(alice.address);
@@ -408,17 +408,17 @@
[alice] = await helper.arrange.createAccounts([10n], donor);
});
});
-
+
itSub('Effective collection limits', async ({helper}) => {
const collection = await helper.nft.mintCollection(alice, {});
- await collection.setLimits(alice, {ownerCanTransfer: true});
-
- {
+ await collection.setLimits(alice, {ownerCanTransfer: true});
+
+ {
// Check that limits are undefined
const collectionInfo = await collection.getData();
const limits = collectionInfo?.raw.limits;
expect(limits).to.be.any;
-
+
expect(limits.accountTokenOwnershipLimit).to.be.null;
expect(limits.sponsoredDataSize).to.be.null;
expect(limits.sponsoredDataRateLimit).to.be.null;
@@ -449,7 +449,7 @@
expect(limits.transfersEnabled).to.be.true;
}
- {
+ {
// Check the values for collection limits
await collection.setLimits(alice, {
accountTokenOwnershipLimit: 99_999,
tests/src/nesting/collectionProperties.seqtest.tsdiffbeforeafterboth--- a/tests/src/nesting/collectionProperties.seqtest.ts
+++ b/tests/src/nesting/collectionProperties.seqtest.ts
@@ -20,7 +20,7 @@
describe('Integration Test: Collection Properties with sudo', () => {
let superuser: IKeyringPair;
let alice: IKeyringPair;
-
+
before(async () => {
await usingPlaygrounds(async (helper, privateKey) => {
superuser = await privateKey('//Alice');
@@ -32,7 +32,7 @@
[
{mode: 'nft' as const, requiredPallets: []},
{mode: 'ft' as const, requiredPallets: []},
- {mode: 'rft' as const, requiredPallets: [Pallets.ReFungible]},
+ {mode: 'rft' as const, requiredPallets: [Pallets.ReFungible]},
].map(testSuite => describe(`${testSuite.mode.toUpperCase()}`, () => {
before(async function() {
// eslint-disable-next-line require-await
tests/src/nesting/collectionProperties.test.tsdiffbeforeafterboth--- a/tests/src/nesting/collectionProperties.test.ts
+++ b/tests/src/nesting/collectionProperties.test.ts
@@ -20,14 +20,14 @@
describe('Integration Test: Collection Properties', () => {
let alice: IKeyringPair;
let bob: IKeyringPair;
-
+
before(async () => {
await usingPlaygrounds(async (helper, privateKey) => {
const donor = await privateKey({filename: __filename});
[alice, bob] = await helper.arrange.createAccounts([200n, 10n], donor);
});
});
-
+
itSub('Properties are initially empty', async ({helper}) => {
const collection = await helper.nft.mintCollection(alice);
expect(await collection.getProperties()).to.be.empty;
@@ -36,7 +36,7 @@
[
{mode: 'nft' as const, requiredPallets: []},
{mode: 'ft' as const, requiredPallets: []},
- {mode: 'rft' as const, requiredPallets: [Pallets.ReFungible]},
+ {mode: 'rft' as const, requiredPallets: [Pallets.ReFungible]},
].map(testSuite => describe(`${testSuite.mode.toUpperCase()}`, () => {
before(async function() {
// eslint-disable-next-line require-await
@@ -50,37 +50,37 @@
// As owner
await expect(collection.setProperties(alice, [{key: 'electron', value: 'come bond'}])).to.be.fulfilled;
-
+
await collection.addAdmin(alice, {Substrate: bob.address});
-
+
// As administrator
await expect(collection.setProperties(bob, [{key: 'black_hole'}])).to.be.fulfilled;
-
+
const properties = await collection.getProperties();
expect(properties).to.include.deep.members([
{key: 'electron', value: 'come bond'},
{key: 'black_hole', value: ''},
]);
});
-
+
itSub('Check valid names for collection properties keys', async ({helper}) => {
const collection = await helper[testSuite.mode].mintCollection(alice);
// alpha symbols
await expect(collection.setProperties(alice, [{key: 'answer'}])).to.be.fulfilled;
-
+
// numeric symbols
await expect(collection.setProperties(alice, [{key: '451'}])).to.be.fulfilled;
-
+
// underscore symbol
await expect(collection.setProperties(alice, [{key: 'black_hole'}])).to.be.fulfilled;
-
+
// dash symbol
await expect(collection.setProperties(alice, [{key: '-'}])).to.be.fulfilled;
-
+
// dot symbol
await expect(collection.setProperties(alice, [{key: 'once.in.a.long.long.while...', value: 'you get a little lost'}])).to.be.fulfilled;
-
+
const properties = await collection.getProperties();
expect(properties).to.include.deep.members([
{key: 'answer', value: ''},
@@ -90,29 +90,29 @@
{key: 'once.in.a.long.long.while...', value: 'you get a little lost'},
]);
});
-
+
itSub('Changes properties of a collection', async ({helper}) => {
const collection = await helper[testSuite.mode].mintCollection(alice);
await expect(collection.setProperties(alice, [{key: 'electron', value: 'come bond'}, {key: 'black_hole', value: ''}])).to.be.fulfilled;
-
+
// Mutate the properties
await expect(collection.setProperties(alice, [{key: 'black_hole', value: 'LIGO'}])).to.be.fulfilled;
-
+
const properties = await collection.getProperties();
expect(properties).to.include.deep.members([
{key: 'electron', value: 'come bond'},
{key: 'black_hole', value: 'LIGO'},
]);
});
-
+
itSub('Deletes properties of a collection', async ({helper}) => {
const collection = await helper[testSuite.mode].mintCollection(alice);
await expect(collection.setProperties(alice, [{key: 'electron', value: 'come bond'}, {key: 'black_hole', value: 'LIGO'}])).to.be.fulfilled;
-
+
await expect(collection.deleteProperties(alice, ['electron'])).to.be.fulfilled;
-
+
const properties = await collection.getProperties(['black_hole', 'electron']);
expect(properties).to.be.deep.equal([
{key: 'black_hole', value: 'LIGO'},
@@ -201,11 +201,11 @@
});
}));
});
-
+
describe('Negative Integration Test: Collection Properties', () => {
let alice: IKeyringPair;
let bob: IKeyringPair;
-
+
before(async () => {
await usingPlaygrounds(async (helper, privateKey) => {
const donor = await privateKey({filename: __filename});
@@ -216,7 +216,7 @@
[
{mode: 'nft' as const, requiredPallets: []},
{mode: 'ft' as const, requiredPallets: []},
- {mode: 'rft' as const, requiredPallets: [Pallets.ReFungible]},
+ {mode: 'rft' as const, requiredPallets: [Pallets.ReFungible]},
].map(testSuite => describe(`${testSuite.mode.toUpperCase()}`, () => {
before(async function() {
// eslint-disable-next-line require-await
@@ -224,21 +224,21 @@
requirePalletsOrSkip(this, helper, testSuite.requiredPallets);
});
});
-
+
itSub('Fails to set properties in a collection if not its onwer/administrator', async ({helper}) => {
const collection = await helper[testSuite.mode].mintCollection(alice);
await expect(collection.setProperties(bob, [{key: 'electron', value: 'come bond'}, {key: 'black_hole', value: 'LIGO'}]))
.to.be.rejectedWith(/common\.NoPermission/);
-
+
expect(await collection.getProperties()).to.be.empty;
});
-
+
itSub('Fails to set properties that exceed the limits', async ({helper}) => {
const collection = await helper[testSuite.mode].mintCollection(alice);
const spaceLimit = (await (collection.helper!.api! as any).query.common.collectionProperties(collection.collectionId)).spaceLimit.toNumber();
-
+
// Mute the general tx parsing error, too many bytes to process
{
console.error = () => {};
@@ -246,17 +246,17 @@
{key: 'electron', value: 'low high '.repeat(Math.ceil(spaceLimit! / 9))},
])).to.be.rejected;
}
-
+
expect(await collection.getProperties(['electron'])).to.be.empty;
-
+
await expect(collection.setProperties(alice, [
- {key: 'electron', value: 'low high '.repeat(Math.ceil(spaceLimit! / 18))},
- {key: 'black_hole', value: '0'.repeat(Math.ceil(spaceLimit! / 2))},
+ {key: 'electron', value: 'low high '.repeat(Math.ceil(spaceLimit! / 18))},
+ {key: 'black_hole', value: '0'.repeat(Math.ceil(spaceLimit! / 2))},
])).to.be.rejectedWith(/common\.NoSpaceForProperty/);
-
+
expect(await collection.getProperties(['electron', 'black_hole'])).to.be.empty;
});
-
+
itSub('Fails to set more properties than it is allowed', async ({helper}) => {
const collection = await helper[testSuite.mode].mintCollection(alice);
@@ -267,10 +267,10 @@
value: Math.random() > 0.5 ? 'high' : 'low',
});
}
-
+
await expect(collection.setProperties(alice, propertiesToBeSet)).
to.be.rejectedWith(/common\.PropertyLimitReached/);
-
+
expect(await collection.getProperties()).to.be.empty;
});
@@ -282,34 +282,34 @@
[{key: 'Mr/Sandman', value: 'Bring me a gene'}],
[{key: 'déjà vu', value: 'hmm...'}],
];
-
+
for (let i = 0; i < invalidProperties.length; i++) {
await expect(
- collection.setProperties(alice, invalidProperties[i]),
+ collection.setProperties(alice, invalidProperties[i]),
`on rejecting the new badly-named property #${i}`,
).to.be.rejectedWith(/common\.InvalidCharacterInPropertyKey/);
}
-
+
await expect(
- collection.setProperties(alice, [{key: '', value: 'nothing must not exist'}]),
+ collection.setProperties(alice, [{key: '', value: 'nothing must not exist'}]),
'on rejecting an unnamed property',
).to.be.rejectedWith(/common\.EmptyPropertyKey/);
-
+
await expect(
- collection.setProperties(alice, [{key: 'CRISPR-Cas9', value: 'rewriting nature!'}]),
+ collection.setProperties(alice, [{key: 'CRISPR-Cas9', value: 'rewriting nature!'}]),
'on setting the correctly-but-still-badly-named property',
).to.be.fulfilled;
-
+
const keys = invalidProperties.flatMap(propertySet => propertySet.map(property => property.key)).concat('CRISPR-Cas9').concat('');
-
+
const properties = await collection.getProperties(keys);
expect(properties).to.be.deep.equal([
{key: 'CRISPR-Cas9', value: 'rewriting nature!'},
]);
-
+
for (let i = 0; i < invalidProperties.length; i++) {
await expect(
- collection.deleteProperties(alice, invalidProperties[i].map(propertySet => propertySet.key)),
+ collection.deleteProperties(alice, invalidProperties[i].map(propertySet => propertySet.key)),
`on trying to delete the non-existent badly-named property #${i}`,
).to.be.rejectedWith(/common\.InvalidCharacterInPropertyKey/);
}
@@ -326,4 +326,3 @@
});
}));
});
-
\ No newline at end of file
tests/src/nesting/graphs.test.tsdiffbeforeafterboth--- a/tests/src/nesting/graphs.test.ts
+++ b/tests/src/nesting/graphs.test.ts
@@ -56,7 +56,7 @@
// to self
await expect(
tokens[0].nest(alice, tokens[0]),
- 'first transaction',
+ 'first transaction',
).to.be.rejectedWith(/structure\.OuroborosDetected/);
// to nested part of graph
await expect(
tests/src/nesting/nest.test.tsdiffbeforeafterboth--- a/tests/src/nesting/nest.test.ts
+++ b/tests/src/nesting/nest.test.ts
@@ -36,7 +36,7 @@
const nestedToken = await collection.mintToken(alice, targetToken.nestingAccount());
expect(await nestedToken.getTopmostOwner()).to.be.deep.equal({Substrate: alice.address});
expect(await nestedToken.getOwner()).to.be.deep.equal(targetToken.nestingAccount().toLowerCase());
-
+
// Create a token to be nested
const newToken = await collection.mintToken(alice);
@@ -66,7 +66,7 @@
// Create a nested token
const tokenC = await collection.mintToken(alice, tokenA.nestingAccount());
expect(await tokenC.getOwner()).to.be.deep.equal(tokenA.nestingAccount().toLowerCase());
-
+
// Transfer the nested token to another token
await expect(tokenC.transferFrom(alice, tokenA.nestingAccount(), tokenB.nestingAccount())).to.be.fulfilled;
expect(await tokenC.getTopmostOwner()).to.be.deep.equal({Substrate: alice.address});
@@ -76,7 +76,7 @@
itSub('Checks token children', async ({helper}) => {
const collectionA = await helper.nft.mintCollection(alice, {permissions: {nesting: {tokenOwner: true}}});
const collectionB = await helper.ft.mintCollection(alice);
-
+
const targetToken = await collectionA.mintToken(alice);
expect((await targetToken.getChildren()).length).to.be.equal(0, 'Children length check at creation');
@@ -108,7 +108,7 @@
{tokenId: 0, collectionId: collectionB.collectionId},
], 'Children contents check at nesting #4 (from another collection)')
.and.be.length(2, 'Children length check at nesting #4 (from another collection)');
-
+
// Move part of the fungible token inside token A deeper in the nesting tree
await collectionB.transferFrom(alice, targetToken.nestingAccount(), tokenA.nestingAccount(), 1n);
expect(await targetToken.getChildren()).to.be.have.deep.members([
tests/src/nesting/propertyPermissions.test.tsdiffbeforeafterboth--- a/tests/src/nesting/propertyPermissions.test.ts
+++ b/tests/src/nesting/propertyPermissions.test.ts
@@ -21,94 +21,94 @@
describe('Integration Test: Access Rights to Token Properties', () => {
let alice: IKeyringPair;
let bob: IKeyringPair;
-
+
before(async () => {
await usingPlaygrounds(async (helper, privateKey) => {
const donor = await privateKey({filename: __filename});
[alice, bob] = await helper.arrange.createAccounts([100n, 10n], donor);
});
});
-
+
itSub('Reads access rights to properties of a collection', async ({helper}) => {
const collection = await helper.nft.mintCollection(alice);
const propertyRights = (await helper.callRpc('api.query.common.collectionPropertyPermissions', [collection.collectionId])).toJSON();
expect(propertyRights).to.be.empty;
});
-
- async function testSetsAccessRightsToProperties(collection: UniqueNFTCollection | UniqueRFTCollection) {
+
+ async function testSetsAccessRightsToProperties(collection: UniqueNFTCollection | UniqueRFTCollection) {
await expect(collection.setTokenPropertyPermissions(alice, [{key: 'skullduggery', permission: {mutable: true}}]))
.to.be.fulfilled;
-
+
await collection.addAdmin(alice, {Substrate: bob.address});
-
+
await expect(collection.setTokenPropertyPermissions(bob, [{key: 'mindgame', permission: {collectionAdmin: true, tokenOwner: false}}]))
.to.be.fulfilled;
-
+
const propertyRights = await collection.getPropertyPermissions(['skullduggery', 'mindgame']);
expect(propertyRights).to.include.deep.members([
{key: 'skullduggery', permission: {mutable: true, collectionAdmin: false, tokenOwner: false}},
{key: 'mindgame', permission: {mutable: false, collectionAdmin: true, tokenOwner: false}},
]);
}
-
+
itSub('Sets access rights to properties of a collection (NFT)', async ({helper}) => {
await testSetsAccessRightsToProperties(await helper.nft.mintCollection(alice));
});
-
+
itSub.ifWithPallets('Sets access rights to properties of a collection (ReFungible)', [Pallets.ReFungible], async ({helper}) => {
await testSetsAccessRightsToProperties(await helper.rft.mintCollection(alice));
});
-
+
async function testChangesAccessRightsToProperty(collection: UniqueNFTCollection | UniqueRFTCollection) {
await expect(collection.setTokenPropertyPermissions(alice, [{key: 'skullduggery', permission: {mutable: true, collectionAdmin: true}}]))
.to.be.fulfilled;
-
+
await expect(collection.setTokenPropertyPermissions(alice, [{key: 'skullduggery', permission: {mutable: false, tokenOwner: true}}]))
.to.be.fulfilled;
-
+
const propertyRights = await collection.getPropertyPermissions();
expect(propertyRights).to.be.deep.equal([
{key: 'skullduggery', permission: {'mutable': false, 'collectionAdmin': false, 'tokenOwner': true}},
]);
}
-
+
itSub('Changes access rights to properties of a NFT collection', async ({helper}) => {
await testChangesAccessRightsToProperty(await helper.nft.mintCollection(alice));
});
-
+
itSub.ifWithPallets('Changes access rights to properties of a ReFungible collection', [Pallets.ReFungible], async ({helper}) => {
await testChangesAccessRightsToProperty(await helper.rft.mintCollection(alice));
});
});
-
+
describe('Negative Integration Test: Access Rights to Token Properties', () => {
let alice: IKeyringPair;
let bob: IKeyringPair;
-
+
before(async () => {
await usingPlaygrounds(async (helper, privateKey) => {
const donor = await privateKey({filename: __filename});
[alice, bob] = await helper.arrange.createAccounts([50n, 10n], donor);
});
});
-
+
async function testPreventsFromSettingAccessRightsNotAdminOrOwner(collection: UniqueNFTCollection | UniqueRFTCollection) {
await expect(collection.setTokenPropertyPermissions(bob, [{key: 'skullduggery', permission: {mutable: true, tokenOwner: true}}]))
.to.be.rejectedWith(/common\.NoPermission/);
-
+
const propertyRights = await collection.getPropertyPermissions(['skullduggery']);
expect(propertyRights).to.be.empty;
}
-
+
itSub('Prevents from setting access rights to properties of a NFT collection if not an onwer/admin', async ({helper}) => {
await testPreventsFromSettingAccessRightsNotAdminOrOwner(await helper.nft.mintCollection(alice));
});
-
+
itSub.ifWithPallets('Prevents from setting access rights to properties of a ReFungible collection if not an onwer/admin', [Pallets.ReFungible], async ({helper}) => {
await testPreventsFromSettingAccessRightsNotAdminOrOwner(await helper.rft.mintCollection(alice));
});
-
- async function testPreventFromAddingTooManyPossibleProperties(collection: UniqueNFTCollection | UniqueRFTCollection) {
+
+ async function testPreventFromAddingTooManyPossibleProperties(collection: UniqueNFTCollection | UniqueRFTCollection) {
const constitution = [];
for (let i = 0; i < 65; i++) {
constitution.push({
@@ -116,82 +116,82 @@
permission: Math.random() > 0.5 ? {mutable: true, collectionAdmin: true, tokenOwner: true} : {},
});
}
-
+
await expect(collection.setTokenPropertyPermissions(alice, constitution))
.to.be.rejectedWith(/common\.PropertyLimitReached/);
-
+
const propertyRights = await collection.getPropertyPermissions();
expect(propertyRights).to.be.empty;
}
-
+
itSub('Prevents from adding too many possible properties (NFT)', async ({helper}) => {
await testPreventFromAddingTooManyPossibleProperties(await helper.nft.mintCollection(alice));
});
-
+
itSub.ifWithPallets('Prevents from adding too many possible properties (ReFungible)', [Pallets.ReFungible], async ({helper}) => {
await testPreventFromAddingTooManyPossibleProperties(await helper.rft.mintCollection(alice));
});
-
+
async function testPreventAccessRightsModifiedIfConstant(collection: UniqueNFTCollection | UniqueRFTCollection) {
await expect(collection.setTokenPropertyPermissions(alice, [{key: 'skullduggery', permission: {mutable: false, tokenOwner: true}}]))
.to.be.fulfilled;
-
+
await expect(collection.setTokenPropertyPermissions(alice, [{key: 'skullduggery', permission: {collectionAdmin: true}}]))
.to.be.rejectedWith(/common\.NoPermission/);
-
+
const propertyRights = await collection.getPropertyPermissions(['skullduggery']);
expect(propertyRights).to.deep.equal([
{key: 'skullduggery', permission: {'mutable': false, 'collectionAdmin': false, 'tokenOwner': true}},
]);
}
-
+
itSub('Prevents access rights to be modified if constant (NFT)', async ({helper}) => {
await testPreventAccessRightsModifiedIfConstant(await helper.nft.mintCollection(alice));
});
-
+
itSub.ifWithPallets('Prevents access rights to be modified if constant (ReFungible)', [Pallets.ReFungible], async ({helper}) => {
await testPreventAccessRightsModifiedIfConstant(await helper.rft.mintCollection(alice));
});
-
+
async function testPreventsAddingPropertiesWithInvalidNames(collection: UniqueNFTCollection | UniqueRFTCollection) {
const invalidProperties = [
[{key: 'skullduggery', permission: {tokenOwner: true}}, {key: 'im possible', permission: {collectionAdmin: true}}],
[{key: 'G#4', permission: {tokenOwner: true}}],
[{key: 'HÆMILTON', permission: {mutable: false, collectionAdmin: true, tokenOwner: true}}],
];
-
+
for (let i = 0; i < invalidProperties.length; i++) {
await expect(
- collection.setTokenPropertyPermissions(alice, invalidProperties[i]),
+ collection.setTokenPropertyPermissions(alice, invalidProperties[i]),
`on setting the new badly-named property #${i}`,
).to.be.rejectedWith(/common\.InvalidCharacterInPropertyKey/);
}
-
+
await expect(
- collection.setTokenPropertyPermissions(alice, [{key: '', permission: {}}]),
+ collection.setTokenPropertyPermissions(alice, [{key: '', permission: {}}]),
'on rejecting an unnamed property',
).to.be.rejectedWith(/common\.EmptyPropertyKey/);
-
+
const correctKey = '--0x03116e387820CA05'; // PolkadotJS would parse this as an already encoded hex-string
await expect(
collection.setTokenPropertyPermissions(alice, [
{key: correctKey, permission: {collectionAdmin: true}},
- ]),
+ ]),
'on setting the correctly-but-still-badly-named property',
).to.be.fulfilled;
-
+
const keys = invalidProperties.flatMap(propertySet => propertySet.map(property => property.key)).concat(correctKey).concat('');
-
+
const propertyRights = await collection.getPropertyPermissions(keys);
expect(propertyRights).to.be.deep.equal([
{key: correctKey, permission: {mutable: false, collectionAdmin: true, tokenOwner: false}},
]);
}
-
+
itSub('Prevents adding properties with invalid names (NFT)', async ({helper}) => {
await testPreventsAddingPropertiesWithInvalidNames(await helper.nft.mintCollection(alice));
});
-
+
itSub.ifWithPallets('Prevents adding properties with invalid names (ReFungible)', [Pallets.ReFungible], async ({helper}) => {
await testPreventsAddingPropertiesWithInvalidNames(await helper.rft.mintCollection(alice));
});
tests/src/nesting/tokenProperties.seqtest.tsdiffbeforeafterboth--- a/tests/src/nesting/tokenProperties.seqtest.ts
+++ b/tests/src/nesting/tokenProperties.seqtest.ts
@@ -31,7 +31,7 @@
[
{mode: 'nft' as const, pieces: undefined, requiredPallets: []},
- {mode: 'rft' as const, pieces: 100n, requiredPallets: [Pallets.ReFungible]},
+ {mode: 'rft' as const, pieces: 100n, requiredPallets: [Pallets.ReFungible]},
].map(testSuite => describe(`${testSuite.mode.toUpperCase()}`, () => {
before(async function() {
// eslint-disable-next-line require-await
@@ -39,7 +39,7 @@
requirePalletsOrSkip(this, helper, testSuite.requiredPallets);
});
});
-
+
itSub('force_repair_item preserves valid consumed space', async({helper}) => {
const propKey = 'tok-prop';
tests/src/nesting/tokenProperties.test.tsdiffbeforeafterboth--- a/tests/src/nesting/tokenProperties.test.ts
+++ b/tests/src/nesting/tokenProperties.test.ts
@@ -43,12 +43,12 @@
async function mintCollectionWithAllPermissionsAndToken(helper: UniqueHelper, mode: 'NFT' | 'RFT'): Promise<[UniqueNFToken | UniqueRFToken, bigint]> {
const collection = await (mode == 'NFT' ? helper.nft : helper.rft).mintCollection(alice, {
- tokenPropertyPermissions: permissions.flatMap(({permission, signers}, i) =>
+ tokenPropertyPermissions: permissions.flatMap(({permission, signers}, i) =>
signers.map(signer => {return {key: `${i+1}_${signer.address}`, permission};})),
});
return mode == 'NFT' ? [await collection.mintToken(alice), 1n] : [await collection.mintToken(alice, 100n), 100n];
}
-
+
async function testReadsYetEmptyProperties(token: UniqueNFToken | UniqueRFToken) {
const properties = await token.getProperties();
expect(properties).to.be.empty;
@@ -84,7 +84,7 @@
propertyKeys.push(key);
await expect(
- token.setProperties(signer, [{key: key, value: 'Serotonin increase'}]),
+ token.setProperties(signer, [{key: key, value: 'Serotonin increase'}]),
`on adding property #${i} by signer #${j}`,
).to.be.fulfilled;
}
@@ -117,7 +117,7 @@
for (const permission of permissions) {
i++;
if (!permission.permission.mutable) continue;
-
+
let j = 0;
for (const signer of permission.signers) {
j++;
@@ -125,12 +125,12 @@
propertyKeys.push(key);
await expect(
- token.setProperties(signer, [{key, value: 'Serotonin increase'}]),
+ token.setProperties(signer, [{key, value: 'Serotonin increase'}]),
`on adding property #${i} by signer #${j}`,
).to.be.fulfilled;
await expect(
- token.setProperties(signer, [{key, value: 'Serotonin stable'}]),
+ token.setProperties(signer, [{key, value: 'Serotonin stable'}]),
`on changing property #${i} by signer #${j}`,
).to.be.fulfilled;
}
@@ -164,7 +164,7 @@
for (const permission of permissions) {
i++;
if (!permission.permission.mutable) continue;
-
+
let j = 0;
for (const signer of permission.signers) {
j++;
@@ -172,12 +172,12 @@
propertyKeys.push(key);
await expect(
- token.setProperties(signer, [{key, value: 'Serotonin increase'}]),
+ token.setProperties(signer, [{key, value: 'Serotonin increase'}]),
`on adding property #${i} by signer #${j}`,
).to.be.fulfilled;
await expect(
- token.deleteProperties(signer, [key]),
+ token.deleteProperties(signer, [key]),
`on deleting property #${i} by signer #${j}`,
).to.be.fulfilled;
}
@@ -186,7 +186,7 @@
expect(await token.getProperties(propertyKeys)).to.be.empty;
expect((await token.getData())!.properties).to.be.empty;
}
-
+
itSub('Deletes properties of a token according to permissions (NFT)', async ({helper}) => {
const [token, amount] = await mintCollectionWithAllPermissionsAndToken(helper, 'NFT');
await testDeletePropertiesAccordingPermission(token, amount);
@@ -200,7 +200,7 @@
itSub('Assigns properties to a nested token according to permissions', async ({helper}) => {
const collectionA = await helper.nft.mintCollection(alice, {permissions: {nesting: {tokenOwner: true}}});
const collectionB = await helper.nft.mintCollection(alice, {
- tokenPropertyPermissions: permissions.flatMap(({permission, signers}, i) =>
+ tokenPropertyPermissions: permissions.flatMap(({permission, signers}, i) =>
signers.map(signer => {return {key: `${i+1}_${signer.address}`, permission};})),
});
const targetToken = await collectionA.mintToken(alice);
@@ -220,7 +220,7 @@
propertyKeys.push(key);
await expect(
- nestedToken.setProperties(signer, [{key, value: 'Serotonin increase'}]),
+ nestedToken.setProperties(signer, [{key, value: 'Serotonin increase'}]),
`on adding property #${i} by signer #${j}`,
).to.be.fulfilled;
}
@@ -238,7 +238,7 @@
itSub('Changes properties of a nested token according to permissions', async ({helper}) => {
const collectionA = await helper.nft.mintCollection(alice, {permissions: {nesting: {tokenOwner: true}}});
const collectionB = await helper.nft.mintCollection(alice, {
- tokenPropertyPermissions: permissions.flatMap(({permission, signers}, i) =>
+ tokenPropertyPermissions: permissions.flatMap(({permission, signers}, i) =>
signers.map(signer => {return {key: `${i+1}_${signer.address}`, permission};})),
});
const targetToken = await collectionA.mintToken(alice);
@@ -252,7 +252,7 @@
for (const permission of permissions) {
i++;
if (!permission.permission.mutable) continue;
-
+
let j = 0;
for (const signer of permission.signers) {
j++;
@@ -260,12 +260,12 @@
propertyKeys.push(key);
await expect(
- nestedToken.setProperties(signer, [{key, value: 'Serotonin increase'}]),
+ nestedToken.setProperties(signer, [{key, value: 'Serotonin increase'}]),
`on adding property #${i} by signer #${j}`,
).to.be.fulfilled;
await expect(
- nestedToken.setProperties(signer, [{key, value: 'Serotonin stable'}]),
+ nestedToken.setProperties(signer, [{key, value: 'Serotonin stable'}]),
`on changing property #${i} by signer #${j}`,
).to.be.fulfilled;
}
@@ -283,7 +283,7 @@
itSub('Deletes properties of a nested token according to permissions', async ({helper}) => {
const collectionA = await helper.nft.mintCollection(alice, {permissions: {nesting: {tokenOwner: true}}});
const collectionB = await helper.nft.mintCollection(alice, {
- tokenPropertyPermissions: permissions.flatMap(({permission, signers}, i) =>
+ tokenPropertyPermissions: permissions.flatMap(({permission, signers}, i) =>
signers.map(signer => {return {key: `${i+1}_${signer.address}`, permission};})),
});
const targetToken = await collectionA.mintToken(alice);
@@ -297,7 +297,7 @@
for (const permission of permissions) {
i++;
if (!permission.permission.mutable) continue;
-
+
let j = 0;
for (const signer of permission.signers) {
j++;
@@ -305,12 +305,12 @@
propertyKeys.push(key);
await expect(
- nestedToken.setProperties(signer, [{key, value: 'Serotonin increase'}]),
+ nestedToken.setProperties(signer, [{key, value: 'Serotonin increase'}]),
`on adding property #${i} by signer #${j}`,
).to.be.fulfilled;
await expect(
- nestedToken.deleteProperties(signer, [key]),
+ nestedToken.deleteProperties(signer, [key]),
`on deleting property #${i} by signer #${j}`,
).to.be.fulfilled;
}
@@ -323,7 +323,7 @@
[
{mode: 'nft' as const, storage: 'nonfungible' as const, pieces: undefined, requiredPallets: []},
- {mode: 'rft' as const, storage: 'refungible' as const, pieces: 100n, requiredPallets: [Pallets.ReFungible]},
+ {mode: 'rft' as const, storage: 'refungible' as const, pieces: 100n, requiredPallets: [Pallets.ReFungible]},
].map(testCase =>
itSub.ifWithPallets(`Allows modifying a token property multiple times with the same size (${testCase.mode})`, testCase.requiredPallets, async({helper}) => {
const propKey = 'tok-prop';
@@ -370,7 +370,7 @@
[
{mode: 'nft' as const, pieces: undefined, requiredPallets: []},
- {mode: 'rft' as const, pieces: 100n, requiredPallets: [Pallets.ReFungible]},
+ {mode: 'rft' as const, pieces: 100n, requiredPallets: [Pallets.ReFungible]},
].map(testCase =>
itSub.ifWithPallets(`Adding then removing a token property doesn't change the consumed space (${testCase.mode})`, testCase.requiredPallets, async({helper}) => {
const propKey = 'tok-prop';
@@ -404,7 +404,7 @@
[
{mode: 'nft' as const, pieces: undefined, requiredPallets: []},
- {mode: 'rft' as const, pieces: 100n, requiredPallets: [Pallets.ReFungible]},
+ {mode: 'rft' as const, pieces: 100n, requiredPallets: [Pallets.ReFungible]},
].map(testCase =>
itSub.ifWithPallets(`Modifying a token property with different sizes correctly changes the consumed space (${testCase.mode})`, testCase.requiredPallets, async({helper}) => {
const propKey = 'tok-prop';
@@ -497,12 +497,12 @@
i++;
const signer = passage.signers[0];
await expect(
- token.setProperties(signer, [{key: `${i}`, value: 'Serotonin increase'}]),
+ token.setProperties(signer, [{key: `${i}`, value: 'Serotonin increase'}]),
`on adding property ${i} by ${signer.address}`,
).to.be.fulfilled;
}
- const originalSpace = await getConsumedSpace(token.collection.helper.getApi(), token.collectionId, token.tokenId, pieces == 1n ? 'NFT' : 'RFT');
+ const originalSpace = await getConsumedSpace(token.collection.helper.getApi(), token.collectionId, token.tokenId, pieces == 1n ? 'NFT' : 'RFT');
return originalSpace;
}
@@ -515,17 +515,17 @@
if (!forbiddance.permission.mutable) continue;
await expect(
- token.setProperties(forbiddance.sinner, [{key: `${i}`, value: 'Serotonin down'}]),
+ token.setProperties(forbiddance.sinner, [{key: `${i}`, value: 'Serotonin down'}]),
`on failing to change property ${i} by the malefactor`,
).to.be.rejectedWith(/common\.NoPermission/);
await expect(
- token.deleteProperties(forbiddance.sinner, [`${i}`]),
+ token.deleteProperties(forbiddance.sinner, [`${i}`]),
`on failing to delete property ${i} by the malefactor`,
).to.be.rejectedWith(/common\.NoPermission/);
}
- const consumedSpace = await getConsumedSpace(token.collection.helper.getApi(), token.collectionId, token.tokenId, pieces == 1n ? 'NFT' : 'RFT');
+ const consumedSpace = await getConsumedSpace(token.collection.helper.getApi(), token.collectionId, token.tokenId, pieces == 1n ? 'NFT' : 'RFT');
expect(consumedSpace).to.be.equal(originalSpace);
}
@@ -548,17 +548,17 @@
if (permission.permission.mutable) continue;
await expect(
- token.setProperties(permission.signers[0], [{key: `${i}`, value: 'Serotonin down'}]),
+ token.setProperties(permission.signers[0], [{key: `${i}`, value: 'Serotonin down'}]),
`on failing to change property ${i} by signer #0`,
).to.be.rejectedWith(/common\.NoPermission/);
await expect(
- token.deleteProperties(permission.signers[0], [i.toString()]),
+ token.deleteProperties(permission.signers[0], [i.toString()]),
`on failing to delete property ${i} by signer #0`,
).to.be.rejectedWith(/common\.NoPermission/);
}
-
- const consumedSpace = await getConsumedSpace(token.collection.helper.getApi(), token.collectionId, token.tokenId, pieces == 1n ? 'NFT' : 'RFT');
+
+ const consumedSpace = await getConsumedSpace(token.collection.helper.getApi(), token.collectionId, token.tokenId, pieces == 1n ? 'NFT' : 'RFT');
expect(consumedSpace).to.be.equal(originalSpace);
}
@@ -576,23 +576,23 @@
const originalSpace = await prepare(token, pieces);
await expect(
- token.setProperties(alice, [{key: 'non-existent', value: 'I exist!'}]),
+ token.setProperties(alice, [{key: 'non-existent', value: 'I exist!'}]),
'on failing to add a previously non-existent property',
).to.be.rejectedWith(/common\.NoPermission/);
-
+
await expect(
- token.collection.setTokenPropertyPermissions(alice, [{key: 'now-existent', permission: {}}]),
+ token.collection.setTokenPropertyPermissions(alice, [{key: 'now-existent', permission: {}}]),
'on setting a new non-permitted property',
).to.be.fulfilled;
await expect(
- token.setProperties(alice, [{key: 'now-existent', value: 'I exist!'}]),
+ token.setProperties(alice, [{key: 'now-existent', value: 'I exist!'}]),
'on failing to add a property forbidden by the \'None\' permission',
).to.be.rejectedWith(/common\.NoPermission/);
expect(await token.getProperties(['non-existent', 'now-existent'])).to.be.empty;
-
- const consumedSpace = await getConsumedSpace(token.collection.helper.getApi(), token.collectionId, token.tokenId, pieces == 1n ? 'NFT' : 'RFT');
+
+ const consumedSpace = await getConsumedSpace(token.collection.helper.getApi(), token.collectionId, token.tokenId, pieces == 1n ? 'NFT' : 'RFT');
expect(consumedSpace).to.be.equal(originalSpace);
}
@@ -611,9 +611,9 @@
await expect(
token.collection.setTokenPropertyPermissions(alice, [
- {key: 'a_holy_book', permission: {collectionAdmin: true, tokenOwner: true}},
+ {key: 'a_holy_book', permission: {collectionAdmin: true, tokenOwner: true}},
{key: 'young_years', permission: {collectionAdmin: true, tokenOwner: true}},
- ]),
+ ]),
'on setting new permissions for properties',
).to.be.fulfilled;
@@ -625,12 +625,12 @@
}
await expect(token.setProperties(alice, [
- {key: 'a_holy_book', value: 'word '.repeat(3277)},
+ {key: 'a_holy_book', value: 'word '.repeat(3277)},
{key: 'young_years', value: 'neverending'.repeat(1490)},
])).to.be.rejectedWith(/common\.NoSpaceForProperty/);
-
+
expect(await token.getProperties(['a_holy_book', 'young_years'])).to.be.empty;
- const consumedSpace = await getConsumedSpace(token.collection.helper.getApi(), token.collectionId, token.tokenId, pieces == 1n ? 'NFT' : 'RFT');
+ const consumedSpace = await getConsumedSpace(token.collection.helper.getApi(), token.collectionId, token.tokenId, pieces == 1n ? 'NFT' : 'RFT');
expect(consumedSpace).to.be.equal(originalSpace);
}
@@ -646,7 +646,7 @@
[
{mode: 'nft' as const, requiredPallets: []},
- {mode: 'rft' as const, requiredPallets: [Pallets.ReFungible]},
+ {mode: 'rft' as const, requiredPallets: [Pallets.ReFungible]},
].map(testCase =>
itSub.ifWithPallets(`Forbids adding too many propeties to a token (${testCase.mode})`, testCase.requiredPallets, async({helper}) => {
const collection = await helper[testCase.mode].mintCollection(alice);
@@ -667,7 +667,7 @@
[
{mode: 'nft' as const, pieces: undefined, requiredPallets: []},
- {mode: 'rft' as const, pieces: 100n, requiredPallets: [Pallets.ReFungible]},
+ {mode: 'rft' as const, pieces: 100n, requiredPallets: [Pallets.ReFungible]},
].map(testCase =>
itSub.ifWithPallets(`Forbids force_repair_item from non-sudo (${testCase.mode})`, testCase.requiredPallets, async({helper}) => {
const propKey = 'tok-prop';
@@ -712,10 +712,10 @@
async function prepare(helper: UniqueHelper): Promise<UniqueRFToken> {
const collection = await helper.rft.mintCollection(alice);
const token = await collection.mintToken(alice, 100n);
-
+
await collection.addAdmin(alice, {Substrate: bob.address});
await collection.setTokenPropertyPermissions(alice, [{key: 'fractals', permission: {mutable: true, tokenOwner: true}}]);
-
+
return token;
}
@@ -725,7 +725,7 @@
await token.transfer(alice, {Substrate: charlie.address}, 33n);
await expect(token.setProperties(alice, [
- {key: 'fractals', value: 'multiverse'},
+ {key: 'fractals', value: 'multiverse'},
])).to.be.rejectedWith(/common\.NoPermission/);
});
@@ -736,13 +736,13 @@
.to.be.fulfilled;
await expect(token.setProperties(alice, [
- {key: 'fractals', value: 'multiverse'},
+ {key: 'fractals', value: 'multiverse'},
])).to.be.fulfilled;
await token.transfer(alice, {Substrate: charlie.address}, 33n);
await expect(token.setProperties(alice, [
- {key: 'fractals', value: 'want to rule the world'},
+ {key: 'fractals', value: 'want to rule the world'},
])).to.be.rejectedWith(/common\.NoPermission/);
});
@@ -750,7 +750,7 @@
const token = await prepare(helper);
await expect(token.setProperties(alice, [
- {key: 'fractals', value: 'one headline - why believe it'},
+ {key: 'fractals', value: 'one headline - why believe it'},
])).to.be.fulfilled;
await token.transfer(alice, {Substrate: charlie.address}, 33n);
@@ -768,7 +768,7 @@
.to.be.fulfilled;
await expect(token.setProperties(alice, [
- {key: 'fractals', value: 'multiverse'},
+ {key: 'fractals', value: 'multiverse'},
])).to.be.fulfilled;
});
});
tests/src/nesting/unnest.test.tsdiffbeforeafterboth--- a/tests/src/nesting/unnest.test.ts
+++ b/tests/src/nesting/unnest.test.ts
@@ -30,7 +30,7 @@
itSub('NFT: allows the owner to successfully unnest a token', async ({helper}) => {
const collection = await helper.nft.mintCollection(alice, {permissions: {nesting: {tokenOwner: true}}});
const targetToken = await collection.mintToken(alice);
-
+
// Create a nested token
const nestedToken = await collection.mintToken(alice, targetToken.nestingAccount());
@@ -49,7 +49,7 @@
const targetToken = await collection.mintToken(alice);
const collectionFT = await helper.ft.mintCollection(alice);
-
+
// Nest and unnest
await collectionFT.mint(alice, 10n, targetToken.nestingAccount());
await expect(collectionFT.transferFrom(alice, targetToken.nestingAccount(), {Substrate: alice.address}, 9n), 'while unnesting').to.be.fulfilled;
@@ -69,7 +69,7 @@
const targetToken = await collection.mintToken(alice);
const collectionRFT = await helper.rft.mintCollection(alice);
-
+
// Nest and unnest
const token = await collectionRFT.mintToken(alice, 10n, targetToken.nestingAccount());
await expect(token.transferFrom(alice, targetToken.nestingAccount(), {Substrate: alice.address}, 9n), 'while unnesting').to.be.fulfilled;
tests/src/nextSponsoring.test.tsdiffbeforeafterboth--- a/tests/src/nextSponsoring.test.ts
+++ b/tests/src/nextSponsoring.test.ts
@@ -39,7 +39,7 @@
// Check with Disabled sponsoring state
expect(await token.getNextSponsored({Substrate: alice.address})).to.be.null;
-
+
// Check with Unconfirmed sponsoring state
await collection.setSponsor(alice, bob.address);
expect(await token.getNextSponsored({Substrate: alice.address})).to.be.null;
@@ -52,7 +52,7 @@
await token.transfer(alice, {Substrate: bob.address});
expect(await token.getNextSponsored({Substrate: alice.address})).to.be.lessThanOrEqual(SPONSORING_TIMEOUT);
- // Non-existing token
+ // Non-existing token
expect(await collection.getTokenNextSponsored(0, {Substrate: alice.address})).to.be.null;
});
@@ -65,7 +65,7 @@
await collection.setSponsor(alice, bob.address);
await collection.confirmSponsorship(bob);
-
+
// Check with Confirmed sponsoring state
expect(await collection.getTokenNextSponsored(0, {Substrate: alice.address})).to.be.equal(0);
@@ -91,7 +91,7 @@
await token.transfer(alice, {Substrate: bob.address});
expect(await token.getNextSponsored({Substrate: alice.address})).to.be.lessThanOrEqual(SPONSORING_TIMEOUT);
- // Non-existing token
+ // Non-existing token
expect(await collection.getTokenNextSponsored(0, {Substrate: alice.address})).to.be.null;
});
});
tests/src/refungible.test.tsdiffbeforeafterboth--- a/tests/src/refungible.test.ts
+++ b/tests/src/refungible.test.ts
@@ -32,36 +32,36 @@
[alice, bob] = await helper.arrange.createAccounts([100n, 10n], donor);
});
});
-
+
itSub('Create refungible collection and token', async ({helper}) => {
const collection = await helper.rft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'});
const itemCountBefore = await collection.getLastTokenId();
const token = await collection.mintToken(alice, 100n);
-
+
const itemCountAfter = await collection.getLastTokenId();
-
+
// What to expect
expect(token?.tokenId).to.be.gte(itemCountBefore);
expect(itemCountAfter).to.be.equal(itemCountBefore + 1);
expect(itemCountAfter.toString()).to.be.equal(token?.tokenId.toString());
});
-
+
itSub('Checking RPC methods when interacting with maximum allowed values (MAX_REFUNGIBLE_PIECES)', async ({helper}) => {
const collection = await helper.rft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'});
-
+
const token = await collection.mintToken(alice, MAX_REFUNGIBLE_PIECES);
-
+
expect(await collection.getTokenBalance(token.tokenId, {Substrate: alice.address})).to.be.equal(MAX_REFUNGIBLE_PIECES);
-
+
await collection.transferToken(alice, token.tokenId, {Substrate: bob.address}, MAX_REFUNGIBLE_PIECES);
expect(await collection.getTokenBalance(token.tokenId, {Substrate: bob.address})).to.be.equal(MAX_REFUNGIBLE_PIECES);
expect(await token.getTotalPieces()).to.be.equal(MAX_REFUNGIBLE_PIECES);
-
+
await expect(collection.mintToken(alice, MAX_REFUNGIBLE_PIECES + 1n))
.to.eventually.be.rejectedWith(/refungible\.WrongRefungiblePieces/);
});
-
+
itSub('RPC method tokenOwners for refungible collection and token', async ({helper}) => {
const ethAcc = {Ethereum: '0x67fb3503a61b284dc83fa96dceec4192db47dc7c'};
const facelessCrowd = (await helper.arrange.createAccounts(Array(7).fill(0n), donor)).map(keyring => {return {Substrate: keyring.address};});
@@ -72,32 +72,32 @@
await token.transfer(alice, {Substrate: bob.address}, 1000n);
await token.transfer(alice, ethAcc, 900n);
-
+
for (let i = 0; i < 7; i++) {
await token.transfer(alice, facelessCrowd[i], 50n * BigInt(i + 1));
- }
+ }
const owners = await token.getTop10Owners();
// What to expect
expect(owners).to.deep.include.members([{Substrate: alice.address}, ethAcc, {Substrate: bob.address}, ...facelessCrowd]);
expect(owners.length).to.be.equal(10);
-
+
const [eleven] = await helper.arrange.createAccounts([0n], donor);
expect(await token.transfer(alice, {Substrate: eleven.address}, 10n)).to.be.true;
expect((await token.getTop10Owners()).length).to.be.equal(10);
});
-
+
itSub('Transfer token pieces', async ({helper}) => {
const collection = await helper.rft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'});
const token = await collection.mintToken(alice, 100n);
expect(await token.getBalance({Substrate: alice.address})).to.be.equal(100n);
expect(await token.transfer(alice, {Substrate: bob.address}, 60n)).to.be.true;
-
+
expect(await token.getBalance({Substrate: alice.address})).to.be.equal(40n);
expect(await token.getBalance({Substrate: bob.address})).to.be.equal(60n);
-
+
await expect(token.transfer(alice, {Substrate: bob.address}, 41n))
.to.eventually.be.rejectedWith(/common\.TokenValueTooLow/);
});
@@ -111,8 +111,8 @@
// {owner: {Substrate: alice.address}, pieces: 100n},
// ]);
await helper.rft.mintMultipleTokensWithOneOwner(alice, collection.collectionId, {Substrate: alice.address}, [
- {pieces: 1n},
- {pieces: 2n},
+ {pieces: 1n},
+ {pieces: 2n},
{pieces: 100n},
]);
const lastTokenId = await collection.getLastTokenId();
@@ -133,7 +133,7 @@
itSub('Burn all pieces', async ({helper}) => {
const collection = await helper.rft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'});
const token = await collection.mintToken(alice, 100n);
-
+
expect(await collection.doesTokenExist(token.tokenId)).to.be.true;
expect(await token.getBalance({Substrate: alice.address})).to.be.equal(100n);
@@ -146,7 +146,7 @@
const token = await collection.mintToken(alice, 100n);
expect(await collection.doesTokenExist(token.tokenId)).to.be.true;
-
+
expect(await token.getBalance({Substrate: alice.address})).to.be.equal(100n);
expect(await token.transfer(alice, {Substrate: bob.address}, 60n)).to.be.true;
@@ -171,7 +171,7 @@
itSub('Set allowance for token', async ({helper}) => {
const collection = await helper.rft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'});
const token = await collection.mintToken(alice, 100n);
-
+
expect(await token.getBalance({Substrate: alice.address})).to.be.equal(100n);
expect(await token.approve(alice, {Substrate: bob.address}, 60n)).to.be.true;
@@ -190,14 +190,14 @@
expect(await token.repartition(alice, 200n)).to.be.true;
expect(await token.getBalance({Substrate: alice.address})).to.be.equal(200n);
expect(await token.getTotalPieces()).to.be.equal(200n);
-
+
expect(await token.transfer(alice, {Substrate: bob.address}, 110n)).to.be.true;
expect(await token.getBalance({Substrate: alice.address})).to.be.equal(90n);
expect(await token.getBalance({Substrate: bob.address})).to.be.equal(110n);
-
+
await expect(token.repartition(alice, 80n))
.to.eventually.be.rejectedWith(/refungible\.RepartitionWhileNotOwningAllPieces/);
-
+
expect(await token.transfer(alice, {Substrate: bob.address}, 90n)).to.be.true;
expect(await token.getBalance({Substrate: alice.address})).to.be.equal(0n);
expect(await token.getBalance({Substrate: bob.address})).to.be.equal(200n);
@@ -220,7 +220,7 @@
data: [
collection.collectionId,
token.tokenId,
- {substrate: alice.address},
+ {substrate: alice.address},
100n,
],
});
@@ -239,12 +239,12 @@
data: [
collection.collectionId,
token.tokenId,
- {substrate: alice.address},
+ {substrate: alice.address},
50n,
],
});
});
-
+
itSub('Create new collection with properties', async ({helper}) => {
const properties = [{key: 'key1', value: 'val1'}];
const tokenPropertyPermissions = [{key: 'key1', permission: {tokenOwner: true, mutable: false, collectionAdmin: true}}];
@@ -280,7 +280,7 @@
await expect(tokenBob.transfer(alice, {Substrate: charlie.address}, 1n)).to.be.rejectedWith('common.TokenValueTooLow');
await expect(tokenBob.transfer(alice, {Substrate: charlie.address}, 10n)).to.be.rejectedWith('common.TokenValueTooLow');
await expect(tokenBob.transfer(alice, {Substrate: charlie.address}, 100n)).to.be.rejectedWith('common.TokenValueTooLow');
-
+
// 2. Alice cannot transfer non-existing token:
await expect(collection.transferToken(alice, 100, {Substrate: charlie.address}, 0n)).to.be.rejectedWith('common.TokenValueTooLow');
await expect(collection.transferToken(alice, 100, {Substrate: charlie.address}, 1n)).to.be.rejectedWith('common.TokenValueTooLow');
tests/src/removeCollectionAdmin.test.tsdiffbeforeafterboth--- a/tests/src/removeCollectionAdmin.test.ts
+++ b/tests/src/removeCollectionAdmin.test.ts
@@ -94,7 +94,7 @@
itSub('Admin can\'t remove collection admin.', async ({helper}) => {
const collection = await helper.nft.mintCollection(alice, {name: 'RemoveCollectionAdmin-Neg-4', tokenPrefix: 'RCA'});
-
+
await collection.addAdmin(alice, {Substrate: bob.address});
await collection.addAdmin(alice, {Substrate: charlie.address});
tests/src/rpc.test.tsdiffbeforeafterboth--- a/tests/src/rpc.test.ts
+++ b/tests/src/rpc.test.ts
@@ -35,20 +35,20 @@
const owner = (await helper.callRpc('api.rpc.unique.tokenOwner', [collection.collectionId, 0])).toJSON() as any;
expect(owner).to.be.null;
});
-
+
itSub('RPC method tokenOwners for fungible collection and token', async ({helper}) => {
// Set-up a few token owners of all stripes
const ethAcc = {Ethereum: '0x67fb3503a61b284dc83fa96dceec4192db47dc7c'};
const facelessCrowd = (await helper.arrange.createAccounts([0n, 0n, 0n, 0n, 0n, 0n, 0n], donor))
.map(i => {return {Substrate: i.address};});
-
+
const collection = await helper.ft.mintCollection(alice, {name: 'RPC-2', tokenPrefix: 'RPC'});
// mint some maximum (u128) amounts of tokens possible
await collection.mint(alice, (1n << 128n) - 1n);
-
+
await collection.transfer(alice, {Substrate: bob.address}, 1000n);
await collection.transfer(alice, ethAcc, 900n);
-
+
for (let i = 0; i < facelessCrowd.length; i++) {
await collection.transfer(alice, facelessCrowd[i], 1n);
}
@@ -59,7 +59,7 @@
expect(ids).to.deep.include.members([{Substrate: alice.address}, ethAcc, {Substrate: bob.address}, ...facelessCrowd]);
expect(owners.length == 10).to.be.true;
-
+
// Make sure only 10 results are returned with this RPC
const [eleven] = await helper.arrange.createAccounts([0n], donor);
expect(await collection.transfer(alice, {Substrate: eleven.address}, 10n)).to.be.true;
tests/src/scheduler.seqtest.tsdiffbeforeafterboth--- a/tests/src/scheduler.seqtest.ts
+++ b/tests/src/scheduler.seqtest.ts
@@ -47,7 +47,7 @@
const token = await collection.mintToken(alice);
const scheduledId = scheduleKind == 'named' ? helper.arrange.makeScheduledId() : undefined;
const blocksBeforeExecution = 4;
-
+
await token.scheduleAfter(blocksBeforeExecution, {scheduledId})
.transfer(alice, {Substrate: bob.address});
const executionBlock = await helper.chain.getLatestBlockNumber() + blocksBeforeExecution + 1;
@@ -156,7 +156,7 @@
const maxScheduledPerBlock = 50;
let fillScheduledIds = new Array(maxScheduledPerBlock);
let extraScheduledId = undefined;
-
+
if (scheduleKind == 'named') {
const scheduledIds = helper.arrange.makeScheduledIds(maxScheduledPerBlock + 1);
fillScheduledIds = scheduledIds.slice(0, maxScheduledPerBlock);
@@ -641,7 +641,7 @@
const balanceBefore = await helper.balance.getSubstrate(bob.address);
const scheduled = helper.scheduler.scheduleAfter(waitForBlocks, {scheduledId, priority: 42});
-
+
await expect(scheduled.balance.transferToSubstrate(alice, bob.address, amount))
.to.be.rejectedWith(/BadOrigin/);
tests/src/setCollectionLimits.test.tsdiffbeforeafterboth--- a/tests/src/setCollectionLimits.test.ts
+++ b/tests/src/setCollectionLimits.test.ts
@@ -75,7 +75,7 @@
await collection.setLimits(alice, collectionLimits);
const collectionInfo1 = await collection.getEffectiveLimits();
-
+
expect(collectionInfo1.tokenLimit).to.be.equal(tokenLimit);
await collection.setLimits(alice, collectionLimits);
@@ -108,7 +108,7 @@
[alice, bob] = await helper.arrange.createAccounts([20n, 10n], donor);
});
});
-
+
itSub('execute setCollectionLimits for not exists collection', async ({helper}) => {
const nonExistentCollectionId = (1 << 32) - 1;
await expect(helper.collection.setLimits(
@@ -180,7 +180,7 @@
itSub('Setting the higher token limit fails', async ({helper}) => {
const collection = await helper.nft.mintCollection(alice, {name: 'SetCollectionLimits-Neg-4', tokenPrefix: 'SCL'});
-
+
const collectionLimits = {
accountTokenOwnershipLimit: accountTokenOwnershipLimit,
sponsoredMintSize: sponsoredDataSize,
tests/src/setCollectionSponsor.test.tsdiffbeforeafterboth--- a/tests/src/setCollectionSponsor.test.ts
+++ b/tests/src/setCollectionSponsor.test.ts
@@ -37,7 +37,7 @@
Unconfirmed: bob.address,
});
});
-
+
itSub('Set Fungible collection sponsor', async ({helper}) => {
const collection = await helper.ft.mintCollection(alice, {name: 'SetCollectionSponsor-1-FT', tokenPrefix: 'SCS'});
await expect(collection.setSponsor(alice, bob.address)).to.be.not.rejected;
@@ -75,7 +75,7 @@
Unconfirmed: charlie.address,
});
});
-
+
itSub('Collection admin add sponsor', async ({helper}) => {
const collection = await helper.nft.mintCollection(alice, {name: 'SetCollectionSponsor-4', tokenPrefix: 'SCS'});
await collection.addAdmin(alice, {Substrate: bob.address});
tests/src/setPermissions.test.tsdiffbeforeafterboth--- a/tests/src/setPermissions.test.ts
+++ b/tests/src/setPermissions.test.ts
@@ -34,11 +34,11 @@
await collection.setPermissions(alice, {access: 'AllowList', mintMode: true, nesting: {collectionAdmin: true, tokenOwner: true, restricted: [1, 2]}});
await collection.setPermissions(alice, {access: 'AllowList', mintMode: true, nesting: {collectionAdmin: true, tokenOwner: true, restricted: [1, 2]}});
-
+
const permissions = (await collection.getData())?.raw.permissions;
expect(permissions).to.be.deep.equal({
- access: 'AllowList',
- mintMode: true,
+ access: 'AllowList',
+ mintMode: true,
nesting: {collectionAdmin: true, tokenOwner: true, restricted: [1, 2]},
});
});
@@ -49,16 +49,16 @@
await collection.setPermissions(alice, {access: 'AllowList', nesting: {collectionAdmin: false, tokenOwner: true, restricted: [1, 2]}});
expect((await collection.getData())?.raw.permissions).to.be.deep.equal({
- access: 'AllowList',
- mintMode: false,
+ access: 'AllowList',
+ mintMode: false,
nesting: {collectionAdmin: false, tokenOwner: true, restricted: [1, 2]},
});
await collection.setPermissions(alice, {access: 'Normal', mintMode: false, nesting: {}});
await collection.setPermissions(alice, {access: 'Normal', mintMode: false, nesting: {}});
expect((await collection.getData())?.raw.permissions).to.be.deep.equal({
- access: 'Normal',
- mintMode: false,
+ access: 'Normal',
+ mintMode: false,
nesting: {collectionAdmin: false, tokenOwner: false, restricted: null},
});
});
@@ -67,7 +67,7 @@
const collection = await helper.nft.mintCollection(alice, {name: 'SetPermissions-2', tokenPrefix: 'SP'});
await collection.addAdmin(alice, {Substrate: bob.address});
await collection.setPermissions(bob, {access: 'AllowList', mintMode: true});
-
+
expect((await collection.getData())?.raw.permissions.access).to.equal('AllowList');
expect((await collection.getData())?.raw.permissions.mintMode).to.equal(true);
});
tests/src/transfer.nload.tsdiffbeforeafterboth--- a/tests/src/transfer.nload.ts
+++ b/tests/src/transfer.nload.ts
@@ -14,6 +14,7 @@
// You should have received a copy of the GNU General Public License
// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
+/* eslint-disable @typescript-eslint/no-floating-promises */
import os from 'os';
import {IKeyringPair} from '@polkadot/types/types';
import {usingPlaygrounds} from './util';
tests/src/transfer.test.tsdiffbeforeafterboth1// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.2// This file is part of Unique Network.34// Unique Network is free software: you can redistribute it and/or modify5// it under the terms of the GNU General Public License as published by6// the Free Software Foundation, either version 3 of the License, or7// (at your option) any later version.89// Unique Network is distributed in the hope that it will be useful,10// but WITHOUT ANY WARRANTY; without even the implied warranty of11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the12// GNU General Public License for more details.1314// You should have received a copy of the GNU General Public License15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.1617import {IKeyringPair} from '@polkadot/types/types';18import {itEth, usingEthPlaygrounds} from './eth/util';19import {itSub, Pallets, usingPlaygrounds, expect} from './util';2021describe('Integration Test Transfer(recipient, collection_id, item_id, value)', () => {22 let donor: IKeyringPair;23 let alice: IKeyringPair;24 let bob: IKeyringPair;2526 before(async () => {27 await usingPlaygrounds(async (helper, privateKey) => {28 donor = await privateKey({filename: __filename});29 [alice, bob] = await helper.arrange.createAccounts([50n, 10n], donor);30 });31 });32 33 itSub('Balance transfers and check balance', async ({helper}) => {34 const alicesBalanceBefore = await helper.balance.getSubstrate(alice.address);35 const bobsBalanceBefore = await helper.balance.getSubstrate(bob.address);3637 expect(await helper.balance.transferToSubstrate(alice, bob.address, 1n)).to.be.true;3839 const alicesBalanceAfter = await helper.balance.getSubstrate(alice.address);40 const bobsBalanceAfter = await helper.balance.getSubstrate(bob.address);4142 expect(alicesBalanceAfter < alicesBalanceBefore).to.be.true;43 expect(bobsBalanceAfter > bobsBalanceBefore).to.be.true;44 });4546 itSub('Inability to pay fees error message is correct', async ({helper}) => {47 const [zero] = await helper.arrange.createAccounts([0n], donor);4849 // console.error = () => {};50 // The following operation throws an error into the console and the logs. Pay it no heed as long as the test succeeds.51 await expect(helper.balance.transferToSubstrate(zero, donor.address, 1n))52 .to.be.rejectedWith('Inability to pay some fees , e.g. account balance too low');53 });5455 itSub('[nft] User can transfer owned token', async ({helper}) => {56 const collection = await helper.nft.mintCollection(alice, {name: 'Transfer-1-NFT', description: '', tokenPrefix: 'T'});57 const nft = await collection.mintToken(alice);5859 await nft.transfer(alice, {Substrate: bob.address});60 expect(await nft.getOwner()).to.be.deep.equal({Substrate: bob.address});61 });6263 itSub('[fungible] User can transfer owned token', async ({helper}) => {64 const collection = await helper.ft.mintCollection(alice, {name: 'Transfer-1-FT', description: '', tokenPrefix: 'T'});65 await collection.mint(alice, 10n);6667 await collection.transfer(alice, {Substrate: bob.address}, 9n);68 expect(await collection.getBalance({Substrate: bob.address})).to.be.equal(9n);69 expect(await collection.getBalance({Substrate: alice.address})).to.be.equal(1n);70 });7172 itSub.ifWithPallets('[refungible] User can transfer owned token', [Pallets.ReFungible], async ({helper}) => {73 const collection = await helper.rft.mintCollection(alice, {name: 'Transfer-1-RFT', description: '', tokenPrefix: 'T'});74 const rft = await collection.mintToken(alice, 10n);7576 await rft.transfer(alice, {Substrate: bob.address}, 9n);77 expect(await rft.getBalance({Substrate: bob.address})).to.be.equal(9n);78 expect(await rft.getBalance({Substrate: alice.address})).to.be.equal(1n);79 });8081 itSub('[nft] Collection admin can transfer owned token', async ({helper}) => {82 const collection = await helper.nft.mintCollection(alice, {name: 'Transfer-2-NFT', description: '', tokenPrefix: 'T'});83 await collection.addAdmin(alice, {Substrate: bob.address});8485 const nft = await collection.mintToken(bob, {Substrate: bob.address});86 await nft.transfer(bob, {Substrate: alice.address});8788 expect(await nft.getOwner()).to.be.deep.equal({Substrate: alice.address});89 });9091 itSub('[fungible] Collection admin can transfer owned token', async ({helper}) => {92 const collection = await helper.ft.mintCollection(alice, {name: 'Transfer-2-FT', description: '', tokenPrefix: 'T'});93 await collection.addAdmin(alice, {Substrate: bob.address});9495 await collection.mint(bob, 10n, {Substrate: bob.address});96 await collection.transfer(bob, {Substrate: alice.address}, 1n);9798 expect(await collection.getBalance({Substrate: bob.address})).to.be.equal(9n);99 expect(await collection.getBalance({Substrate: alice.address})).to.be.equal(1n);100 });101102 itSub.ifWithPallets('[refungible] Collection admin can transfer owned token', [Pallets.ReFungible], async ({helper}) => {103 const collection = await helper.rft.mintCollection(alice, {name: 'Transfer-2-RFT', description: '', tokenPrefix: 'T'});104 await collection.addAdmin(alice, {Substrate: bob.address});105106 const rft = await collection.mintToken(bob, 10n, {Substrate: bob.address});107 await rft.transfer(bob, {Substrate: alice.address}, 1n);108109 expect(await rft.getBalance({Substrate: bob.address})).to.be.equal(9n);110 expect(await rft.getBalance({Substrate: alice.address})).to.be.equal(1n);111 });112});113114describe('Negative Integration Test Transfer(recipient, collection_id, item_id, value)', () => {115 let alice: IKeyringPair;116 let bob: IKeyringPair;117118 before(async () => {119 await usingPlaygrounds(async (helper, privateKey) => {120 const donor = await privateKey({filename: __filename});121 [alice, bob] = await helper.arrange.createAccounts([50n, 10n], donor);122 });123 });124125126 itSub('[nft] Transfer with not existed collection_id', async ({helper}) => {127 const collectionId = (1 << 32) - 1;128 await expect(helper.nft.transferToken(alice, collectionId, 1, {Substrate: bob.address}))129 .to.be.rejectedWith(/common\.CollectionNotFound/);130 });131132 itSub('[fungible] Transfer with not existed collection_id', async ({helper}) => {133 const collectionId = (1 << 32) - 1;134 await expect(helper.ft.transfer(alice, collectionId, {Substrate: bob.address}))135 .to.be.rejectedWith(/common\.CollectionNotFound/);136 });137138 itSub.ifWithPallets('[refungible] Transfer with not existed collection_id', [Pallets.ReFungible], async ({helper}) => {139 const collectionId = (1 << 32) - 1;140 await expect(helper.rft.transferToken(alice, collectionId, 1, {Substrate: bob.address}))141 .to.be.rejectedWith(/common\.CollectionNotFound/);142 });143144 itSub('[nft] Transfer with deleted collection_id', async ({helper}) => {145 const collection = await helper.nft.mintCollection(alice, {name: 'Transfer-Neg-1-NFT', description: '', tokenPrefix: 'T'});146 const nft = await collection.mintToken(alice);147148 await nft.burn(alice);149 await collection.burn(alice);150151 await expect(nft.transfer(alice, {Substrate: bob.address}))152 .to.be.rejectedWith(/common\.CollectionNotFound/);153 });154155 itSub('[fungible] Transfer with deleted collection_id', async ({helper}) => {156 const collection = await helper.ft.mintCollection(alice, {name: 'Transfer-Neg-1-FT', description: '', tokenPrefix: 'T'});157 await collection.mint(alice, 10n);158159 await collection.burnTokens(alice, 10n);160 await collection.burn(alice);161162 await expect(collection.transfer(alice, {Substrate: bob.address}))163 .to.be.rejectedWith(/common\.CollectionNotFound/);164 });165 166 itSub.ifWithPallets('[refungible] Transfer with deleted collection_id', [Pallets.ReFungible], async ({helper}) => {167 const collection = await helper.rft.mintCollection(alice, {name: 'Transfer-Neg-1-RFT', description: '', tokenPrefix: 'T'});168 const rft = await collection.mintToken(alice, 10n);169170 await rft.burn(alice, 10n);171 await collection.burn(alice);172173 await expect(rft.transfer(alice, {Substrate: bob.address}))174 .to.be.rejectedWith(/common\.CollectionNotFound/);175 });176177 itSub('[nft] Transfer with not existed item_id', async ({helper}) => {178 const collection = await helper.nft.mintCollection(alice, {name: 'Transfer-Neg-2-NFT', description: '', tokenPrefix: 'T'});179 await expect(collection.transferToken(alice, 1, {Substrate: bob.address}))180 .to.be.rejectedWith(/common\.TokenNotFound/);181 });182183 itSub('[fungible] Transfer with not existed item_id', async ({helper}) => {184 const collection = await helper.ft.mintCollection(alice, {name: 'Transfer-Neg-2-FT', description: '', tokenPrefix: 'T'});185 await expect(collection.transfer(alice, {Substrate: bob.address}))186 .to.be.rejectedWith(/common\.TokenValueTooLow/);187 });188189 itSub.ifWithPallets('[refungible] Transfer with not existed item_id', [Pallets.ReFungible], async ({helper}) => {190 const collection = await helper.rft.mintCollection(alice, {name: 'Transfer-Neg-2-RFT', description: '', tokenPrefix: 'T'});191 await expect(collection.transferToken(alice, 1, {Substrate: bob.address}))192 .to.be.rejectedWith(/common\.TokenValueTooLow/);193 });194195 itSub('Zero transfer NFT', async ({helper}) => {196 const collection = await helper.nft.mintCollection(alice, {name: 'Transfer-Neg-3-NFT', description: '', tokenPrefix: 'T'});197 const tokenAlice = await collection.mintToken(alice, {Substrate: alice.address});198 const tokenBob = await collection.mintToken(alice, {Substrate: bob.address});199 // 1. Zero transfer of own tokens allowed:200 await helper.executeExtrinsic(alice, 'api.tx.unique.transfer', [{Substrate: bob.address}, collection.collectionId, tokenAlice.tokenId, 0]);201 // 2. Zero transfer of non-owned tokens not allowed:202 await expect(helper.executeExtrinsic(alice, 'api.tx.unique.transfer', [{Substrate: alice.address}, collection.collectionId, tokenBob.tokenId, 0])).to.be.rejectedWith('common.NoPermission');203 // 3. Zero transfer of non-existing tokens not allowed:204 await expect(helper.executeExtrinsic(alice, 'api.tx.unique.transfer', [{Substrate: alice.address}, collection.collectionId, 10, 0])).to.be.rejectedWith('common.TokenNotFound');205 expect(await tokenAlice.getOwner()).to.deep.eq({Substrate: alice.address});206 expect(await tokenBob.getOwner()).to.deep.eq({Substrate: bob.address});207 // 4. Storage is not corrupted:208 await tokenAlice.transfer(alice, {Substrate: bob.address});209 await tokenBob.transfer(bob, {Substrate: alice.address});210 expect(await tokenAlice.getOwner()).to.deep.eq({Substrate: bob.address});211 expect(await tokenBob.getOwner()).to.deep.eq({Substrate: alice.address});212 });213214 itSub('[nft] Transfer with deleted item_id', async ({helper}) => {215 const collection = await helper.nft.mintCollection(alice, {name: 'Transfer-Neg-3-NFT', description: '', tokenPrefix: 'T'});216 const nft = await collection.mintToken(alice);217218 await nft.burn(alice);219220 await expect(nft.transfer(alice, {Substrate: bob.address}))221 .to.be.rejectedWith(/common\.TokenNotFound/);222 });223224 itSub('[fungible] Transfer with deleted item_id', async ({helper}) => {225 const collection = await helper.ft.mintCollection(alice, {name: 'Transfer-Neg-3-FT', description: '', tokenPrefix: 'T'});226 await collection.mint(alice, 10n);227228 await collection.burnTokens(alice, 10n);229230 await expect(collection.transfer(alice, {Substrate: bob.address}))231 .to.be.rejectedWith(/common\.TokenValueTooLow/);232 });233234 itSub.ifWithPallets('[refungible] Transfer with deleted item_id', [Pallets.ReFungible], async ({helper}) => {235 const collection = await helper.rft.mintCollection(alice, {name: 'Transfer-Neg-3-RFT', description: '', tokenPrefix: 'T'});236 const rft = await collection.mintToken(alice, 10n);237238 await rft.burn(alice, 10n);239240 await expect(rft.transfer(alice, {Substrate: bob.address}))241 .to.be.rejectedWith(/common\.TokenValueTooLow/);242 });243244 itSub('[nft] Transfer with recipient that is not owner', async ({helper}) => {245 const collection = await helper.nft.mintCollection(alice, {name: 'Transfer-Neg-4-NFT', description: '', tokenPrefix: 'T'});246 const nft = await collection.mintToken(alice);247248 await expect(nft.transfer(bob, {Substrate: bob.address}))249 .to.be.rejectedWith(/common\.NoPermission/);250 expect(await nft.getOwner()).to.be.deep.equal({Substrate: alice.address});251 });252253 itSub('[fungible] Transfer with recipient that is not owner', async ({helper}) => {254 const collection = await helper.ft.mintCollection(alice, {name: 'Transfer-Neg-4-FT', description: '', tokenPrefix: 'T'});255 await collection.mint(alice, 10n);256257 await expect(collection.transfer(bob, {Substrate: bob.address}, 9n))258 .to.be.rejectedWith(/common\.TokenValueTooLow/);259 expect(await collection.getBalance({Substrate: bob.address})).to.be.equal(0n);260 expect(await collection.getBalance({Substrate: alice.address})).to.be.equal(10n);261 });262263 itSub.ifWithPallets('[refungible] Transfer with recipient that is not owner', [Pallets.ReFungible], async ({helper}) => {264 const collection = await helper.rft.mintCollection(alice, {name: 'Transfer-1-RFT', description: '', tokenPrefix: 'T'});265 const rft = await collection.mintToken(alice, 10n);266267 await expect(rft.transfer(bob, {Substrate: bob.address}, 9n))268 .to.be.rejectedWith(/common\.TokenValueTooLow/);269 expect(await rft.getBalance({Substrate: bob.address})).to.be.equal(0n);270 expect(await rft.getBalance({Substrate: alice.address})).to.be.equal(10n);271 });272});273274describe('Transfers to self (potentially over substrate-evm boundary)', () => {275 let donor: IKeyringPair;276277 before(async function() {278 await usingEthPlaygrounds(async (_, privateKey) => {279 donor = await privateKey({filename: __filename});280 });281 });282 283 itEth('Transfers to self. In case of same frontend', async ({helper}) => {284 const [owner] = await helper.arrange.createAccounts([10n], donor);285 const collection = await helper.ft.mintCollection(owner, {});286 await collection.mint(owner, 100n);287288 const ownerProxy = helper.address.substrateToEth(owner.address);289290 // transfer to own proxy291 await collection.transfer(owner, {Ethereum: ownerProxy}, 10n);292 expect(await collection.getBalance({Substrate: owner.address})).to.be.equal(90n);293 expect(await collection.getBalance({Ethereum: ownerProxy})).to.be.equal(10n);294295 // transfer-from own proxy to own proxy again296 await collection.transferFrom(owner, {Ethereum: ownerProxy}, {Ethereum: ownerProxy}, 5n);297 expect(await collection.getBalance({Substrate: owner.address})).to.be.equal(90n);298 expect(await collection.getBalance({Ethereum: ownerProxy})).to.be.equal(10n);299 });300301 itEth('Transfers to self. In case of substrate-evm boundary', async ({helper}) => {302 const [owner] = await helper.arrange.createAccounts([10n], donor);303 const collection = await helper.ft.mintCollection(owner, {});304 await collection.mint(owner, 100n);305306 const ownerProxy = helper.address.substrateToEth(owner.address);307308 // transfer to own proxy309 await collection.transfer(owner, {Ethereum: ownerProxy}, 10n);310 expect(await collection.getBalance({Substrate: owner.address})).to.be.equal(90n);311 expect(await collection.getBalance({Ethereum: ownerProxy})).to.be.equal(10n);312313 // transfer-from own proxy to self314 await collection.transferFrom(owner, {Ethereum: ownerProxy}, {Substrate: owner.address}, 5n);315 expect(await collection.getBalance({Substrate: owner.address})).to.be.equal(95n);316 expect(await collection.getBalance({Ethereum: ownerProxy})).to.be.equal(5n);317 });318319 itEth('Transfers to self. In case of inside substrate-evm', async ({helper}) => {320 const [owner] = await helper.arrange.createAccounts([10n], donor);321 const collection = await helper.ft.mintCollection(owner, {});322 await collection.mint(owner, 100n);323324 // transfer to self again325 await collection.transfer(owner, {Substrate: owner.address}, 10n);326 expect(await collection.getBalance({Substrate: owner.address})).to.be.equal(100n);327328 // transfer-from self to self again329 await collection.transferFrom(owner, {Substrate: owner.address}, {Substrate: owner.address}, 5n);330 expect(await collection.getBalance({Substrate: owner.address})).to.be.equal(100n);331 });332333 itEth('Transfers to self. In case of inside substrate-evm when not enought "Fungibles"', async ({helper}) => {334 const [owner] = await helper.arrange.createAccounts([10n], donor);335 const collection = await helper.ft.mintCollection(owner, {});336 await collection.mint(owner, 10n);337338 // transfer to self again339 await expect(collection.transfer(owner, {Substrate: owner.address}, 11n))340 .to.be.rejectedWith(/common\.TokenValueTooLow/);341342 // transfer-from self to self again343 await expect(collection.transferFrom(owner, {Substrate: owner.address}, {Substrate: owner.address}, 12n))344 .to.be.rejectedWith(/common\.TokenValueTooLow/);345 expect(await collection.getBalance({Substrate: owner.address})).to.be.equal(10n);346 });347});tests/src/transferFrom.test.tsdiffbeforeafterboth--- a/tests/src/transferFrom.test.ts
+++ b/tests/src/transferFrom.test.ts
@@ -44,7 +44,7 @@
await collection.mint(alice, 10n);
await collection.approveTokens(alice, {Substrate: bob.address}, 7n);
expect(await collection.getApprovedTokens({Substrate: alice.address}, {Substrate: bob.address})).to.be.equal(7n);
-
+
await collection.transferFrom(bob, {Substrate: alice.address}, {Substrate: charlie.address}, 6n);
expect(await collection.getBalance({Substrate: charlie.address})).to.be.equal(6n);
expect(await collection.getBalance({Substrate: alice.address})).to.be.equal(4n);
@@ -56,7 +56,7 @@
const rft = await collection.mintToken(alice, 10n);
await rft.approve(alice, {Substrate: bob.address}, 7n);
expect(await rft.getApprovedPieces({Substrate: alice.address}, {Substrate: bob.address})).to.be.equal(7n);
-
+
await rft.transferFrom(bob, {Substrate: alice.address}, {Substrate: charlie.address}, 6n);
expect(await rft.getBalance({Substrate: charlie.address})).to.be.equal(6n);
expect(await rft.getBalance({Substrate: alice.address})).to.be.equal(4n);
@@ -155,11 +155,11 @@
expect(await nft.isApproved({Substrate: bob.address})).to.be.true;
await expect(helper.collection.transferTokenFrom(
- bob,
- collection.collectionId,
- nft.tokenId,
- {Substrate: alice.address},
- {Substrate: charlie.address},
+ bob,
+ collection.collectionId,
+ nft.tokenId,
+ {Substrate: alice.address},
+ {Substrate: charlie.address},
2n,
)).to.be.rejectedWith(/nonfungible\.NonfungibleItemsHaveNoAmount/);
expect(await nft.getOwner()).to.be.deep.equal({Substrate: alice.address});
@@ -202,7 +202,7 @@
await expect(nft.transferFrom(
charlie,
- {Substrate: alice.address},
+ {Substrate: alice.address},
{Substrate: charlie.address},
)).to.be.rejectedWith(/common\.ApprovedValueTooLow/);
expect(await nft.getOwner()).to.be.deep.equal({Substrate: alice.address});
@@ -218,7 +218,7 @@
await expect(collection.transferFrom(
charlie,
- {Substrate: alice.address},
+ {Substrate: alice.address},
{Substrate: charlie.address},
)).to.be.rejectedWith(/common\.ApprovedValueTooLow/);
expect(await collection.getBalance({Substrate: alice.address})).to.be.deep.equal(10000n);
@@ -236,7 +236,7 @@
await expect(rft.transferFrom(
charlie,
- {Substrate: alice.address},
+ {Substrate: alice.address},
{Substrate: charlie.address},
)).to.be.rejectedWith(/common\.ApprovedValueTooLow/);
expect(await rft.getBalance({Substrate: alice.address})).to.be.deep.equal(10000n);
@@ -254,7 +254,7 @@
await expect(nft.transferFrom(
bob,
- {Substrate: alice.address},
+ {Substrate: alice.address},
{Substrate: charlie.address},
)).to.be.rejectedWith(/common\.ApprovedValueTooLow/);
});
@@ -269,7 +269,7 @@
await expect(collection.transferFrom(
alice,
- {Substrate: alice.address},
+ {Substrate: alice.address},
{Substrate: charlie.address},
)).to.be.rejectedWith(/common\.TokenValueTooLow/);
});
@@ -284,7 +284,7 @@
await expect(rft.transferFrom(
alice,
- {Substrate: alice.address},
+ {Substrate: alice.address},
{Substrate: charlie.address},
)).to.be.rejectedWith(/common\.TokenValueTooLow/);
});
@@ -300,7 +300,7 @@
await expect(nft.transferFrom(
bob,
- {Substrate: alice.address},
+ {Substrate: alice.address},
{Substrate: charlie.address},
)).to.be.rejectedWith(/common\.ApprovedValueTooLow/);
});
@@ -316,7 +316,7 @@
await expect(collection.transferFrom(
bob,
- {Substrate: alice.address},
+ {Substrate: alice.address},
{Substrate: charlie.address},
)).to.be.rejectedWith(/common\.TokenValueTooLow/);
});
@@ -332,7 +332,7 @@
await expect(rft.transferFrom(
bob,
- {Substrate: alice.address},
+ {Substrate: alice.address},
{Substrate: charlie.address},
)).to.be.rejectedWith(/common\.ApprovedValueTooLow/);
});
@@ -345,7 +345,7 @@
await expect(nft.transferFrom(
alice,
- {Substrate: bob.address},
+ {Substrate: bob.address},
{Substrate: charlie.address},
)).to.be.rejectedWith(/common\.ApprovedValueTooLow/);
});
tests/src/util/globalSetup.tsdiffbeforeafterboth--- a/tests/src/util/globalSetup.ts
+++ b/tests/src/util/globalSetup.ts
@@ -17,10 +17,10 @@
// 2. Create donors for test files
await fundFilenamesWithRetries(3)
.then((result) => {
- if (!result) Promise.reject();
+ if (!result) throw Error('Some problems with fundFilenamesWithRetries');
});
- // 3. Configure App Promotion
+ // 3. Configure App Promotion
const missingPallets = helper.fetchMissingPalletNames([Pallets.AppPromotion]);
if (missingPallets.length === 0) {
const superuser = await privateKey('//Alice');
@@ -38,7 +38,7 @@
}
} catch (error) {
console.error(error);
- Promise.reject();
+ throw Error('Error during globalSetup');
}
});
};
@@ -78,7 +78,7 @@
if (aliceBalance < MINIMUM_DONOR_FUND * oneToken) {
tx.push(helper.executeExtrinsic(
- alice,
+ alice,
'api.tx.balances.transfer',
[account.address, DONOR_FUNDING * oneToken],
true,
tests/src/util/index.tsdiffbeforeafterboth--- a/tests/src/util/index.ts
+++ b/tests/src/util/index.ts
@@ -41,7 +41,7 @@
else {
const actualSeed = getTestSeed(seed.filename);
let account = helper.util.fromSeed(actualSeed, ss58Format);
- // here's to hoping that no
+ // here's to hoping that no
if (!seed.ignoreFundsPresence && ((helper as any)['balance'] == undefined || await (helper as any).balance.getSubstrate(account.address) < MINIMUM_DONOR_FUND)) {
console.warn(`${path.basename(seed.filename)}: Not enough funds present on the filename account. Using the default one as the donor instead.`);
account = helper.util.fromSeed('//Alice', ss58Format);
@@ -115,7 +115,7 @@
export function requirePalletsOrSkip(test: Context, helper: DevUniqueHelper, requiredPallets: string[]) {
const missingPallets = helper.fetchMissingPalletNames(requiredPallets);
-
+
if (missingPallets.length > 0) {
const skipMsg = `\tSkipping test '${test.test?.title}'.\n\tThe following pallets are missing:\n\t- ${missingPallets.join('\n\t- ')}`;
console.warn('\x1b[38:5:208m%s\x1b[0m', skipMsg);
@@ -124,13 +124,13 @@
}
export function itSub(name: string, cb: (apis: { helper: DevUniqueHelper, privateKey: (seed: string) => Promise<IKeyringPair> }) => any, opts: { only?: boolean, skip?: boolean, requiredPallets?: string[] } = {}) {
- (opts.only ? it.only :
+ (opts.only ? it.only :
opts.skip ? it.skip : it)(name, async function () {
await usingPlaygrounds(async (helper, privateKey) => {
if (opts.requiredPallets) {
requirePalletsOrSkip(this, helper, opts.requiredPallets);
}
-
+
await cb({helper, privateKey});
});
});
tests/src/util/playgrounds/types.tsdiffbeforeafterboth--- a/tests/src/util/playgrounds/types.ts
+++ b/tests/src/util/playgrounds/types.ts
@@ -26,7 +26,7 @@
export interface ISubscribeBlockEventsData {
number: number;
hash: string;
- timestamp: number;
+ timestamp: number;
events: IEvent[];
}
@@ -56,7 +56,7 @@
connected?: (...args: any[]) => any;
disconnected?: (...args: any[]) => any;
error?: (...args: any[]) => any;
- ready?: (...args: any[]) => any;
+ ready?: (...args: any[]) => any;
decorated?: (...args: any[]) => any;
}
tests/src/util/playgrounds/unique.dev.tsdiffbeforeafterboth--- a/tests/src/util/playgrounds/unique.dev.ts
+++ b/tests/src/util/playgrounds/unique.dev.ts
@@ -35,7 +35,7 @@
this.consoleWarn = console.warn;
}
- enable() {
+ enable() {
const outFn = (printer: any) => (...args: any[]) => {
for (const arg of args) {
if (typeof arg !== 'string')
@@ -45,7 +45,7 @@
}
printer(...args);
};
-
+
console.error = outFn(this.consoleErr.bind(console));
console.log = outFn(this.consoleLog.bind(console));
console.warn = outFn(this.consoleWarn.bind(console));
@@ -188,11 +188,11 @@
}
/**
- * Generates accounts with the specified UNQ token balance
+ * Generates accounts with the specified UNQ token balance
* @param balances balances for generated accounts. Each balance will be multiplied by the token nominal.
* @param donor donor account for balances
* @returns array of newly created accounts
- * @example const [acc1, acc2, acc3] = await createAccounts([0n, 10n, 20n], donor);
+ * @example const [acc1, acc2, acc3] = await createAccounts([0n, 10n, 20n], donor);
*/
createAccounts = async (balances: bigint[], donor: IKeyringPair): Promise<IKeyringPair[]> => {
let nonce = await this.helper.chain.getNonce(donor.address);
@@ -212,7 +212,7 @@
}
await Promise.all(transactions).catch(_e => {});
-
+
//#region TODO remove this region, when nonce problem will be solved
const checkBalances = async () => {
let isSuccess = true;
@@ -242,7 +242,7 @@
};
// TODO combine this method and createAccounts into one
- createCrowd = async (accountsToCreate: number, withBalance: bigint, donor: IKeyringPair): Promise<IKeyringPair[]> => {
+ createCrowd = async (accountsToCreate: number, withBalance: bigint, donor: IKeyringPair): Promise<IKeyringPair[]> => {
const createAsManyAsCan = async () => {
let transactions: any = [];
const accounts: IKeyringPair[] = [];
@@ -250,9 +250,9 @@
const tokenNominal = this.helper.balance.getOneTokenNominal();
for (let i = 0; i < accountsToCreate; i++) {
if (i === 500) { // if there are too many accounts to create
- await Promise.allSettled(transactions); // wait while first 500 (should be 100 for devnode) tx will be settled
+ await Promise.allSettled(transactions); // wait while first 500 (should be 100 for devnode) tx will be settled
transactions = []; //
- nonce = await this.helper.chain.getNonce(donor.address); // update nonce
+ nonce = await this.helper.chain.getNonce(donor.address); // update nonce
}
const recepient = this.helper.util.fromSeed(mnemonicGenerate());
accounts.push(recepient);
@@ -262,7 +262,7 @@
nonce++;
}
}
-
+
const fullfilledAccounts = [];
await Promise.allSettled(transactions);
for (const account of accounts) {
@@ -274,7 +274,7 @@
return fullfilledAccounts;
};
-
+
const crowd: IKeyringPair[] = [];
// do up to 5 retries
for (let index = 0; index < 5 && accountsToCreate !== 0; index++) {
@@ -291,7 +291,7 @@
isDevNode = async () => {
let blockNumber = (await this.helper.callRpc('api.query.system.number')).toJSON();
if (blockNumber == 0) {
- await this.helper.wait.newBlocks(1);
+ await this.helper.wait.newBlocks(1);
blockNumber = (await this.helper.callRpc('api.query.system.number')).toJSON();
}
const block2 = await this.helper.callRpc('api.rpc.chain.getBlock', [await this.helper.callRpc('api.rpc.chain.getBlockHash', [blockNumber])]);
@@ -310,15 +310,15 @@
const block2date = await findCreationDate(block2);
if(block2date! - block1date! < 9000) return true;
};
-
+
async calculcateFee(payer: ICrossAccountId, promise: () => Promise<any>): Promise<bigint> {
const address = payer.Substrate ? payer.Substrate : await this.helper.address.ethToSubstrate(payer.Ethereum!);
- let balance = await this.helper.balance.getSubstrate(address);
-
+ let balance = await this.helper.balance.getSubstrate(address);
+
await promise();
-
+
balance -= await this.helper.balance.getSubstrate(address);
-
+
return balance;
}
@@ -335,7 +335,7 @@
const scheduledId = '0x' + '0'.repeat(prefixSize) + hexId;
- return scheduledId;
+ return scheduledId;
}
const ids = [];
@@ -424,7 +424,7 @@
/**
* Wait for specified number of blocks
* @param blocksCount number of blocks to wait
- * @returns
+ * @returns
*/
async newBlocks(blocksCount = 1, timeout?: number): Promise<void> {
timeout = timeout ?? blocksCount * 60_000;
@@ -457,7 +457,7 @@
await this.waitWithTimeout(promise, timeout);
return promise;
}
-
+
async forRelayBlockNumber(blockNumber: bigint | number, timeout?: number) {
timeout = timeout ?? 30 * 60 * 1000;
// eslint-disable-next-line no-async-promise-executor
@@ -476,7 +476,7 @@
noScheduledTasks() {
const api = this.helper.getApi();
-
+
// eslint-disable-next-line no-async-promise-executor
const promise = new Promise<void>(async resolve => {
const unsubscribe = await api.rpc.chain.subscribeNewHeads(async () => {
@@ -486,7 +486,7 @@
unsubscribe();
resolve();
}
- });
+ });
});
return promise;
@@ -500,16 +500,16 @@
const blockHash = header.hash;
const eventIdStr = `${eventSection}.${eventMethod}`;
const waitLimitStr = `wait blocks remaining: ${maxBlocksToWait}`;
-
+
this.helper.logger.log(`[Block #${blockNumber}] Waiting for event \`${eventIdStr}\` (${waitLimitStr})`);
-
+
const apiAt = await this.helper.getApi().at(blockHash);
const eventRecords = (await apiAt.query.system.events()) as any;
-
+
const neededEvent = eventRecords.toArray().find((r: FrameSystemEventRecord) => {
return r.event.section == eventSection && r.event.method == eventMethod;
});
-
+
if (neededEvent) {
unsubscribe();
resolve(neededEvent);
tests/src/util/playgrounds/unique.tsdiffbeforeafterboth--- a/tests/src/util/playgrounds/unique.ts
+++ b/tests/src/util/playgrounds/unique.ts
@@ -1103,7 +1103,7 @@
async getPropertiesConsumedSpace(collectionId: number): Promise<number> {
const api = this.helper.getApi();
const props = (await api.query.common.collectionProperties(collectionId)).toJSON();
-
+
return (props! as any).consumedSpace;
}
@@ -2423,7 +2423,7 @@
/**
* Get schedule for recepient of vested transfer
* @param address Substrate address of recipient
- * @returns
+ * @returns
*/
async getVestingSchedules(address: TSubstrateAccount): Promise<{start: bigint, period: bigint, periodCount: bigint, perPeriod: bigint}[]> {
const schedule = (await this.helper.callRpc('api.query.vesting.vestingSchedules', [address])).toJSON();
@@ -2506,16 +2506,16 @@
: typeof key === 'bigint'
? hexToU8a(key.toString(16))
: key;
-
+
if (ss58Format < 0 || ss58Format > 16383 || [46, 47].includes(ss58Format)) {
throw new Error(`ss58Format is not valid, received ${typeof ss58Format} "${ss58Format}"`);
}
-
+
const allowedDecodedLengths = [1, 2, 4, 8, 32, 33];
if (!allowedDecodedLengths.includes(u8a.length)) {
throw new Error(`key length is not valid, received ${u8a.length}, valid values are ${allowedDecodedLengths.join(', ')}`);
}
-
+
const u8aPrefix = ss58Format < 64
? new Uint8Array([ss58Format])
: new Uint8Array([
@@ -2524,7 +2524,7 @@
]);
const input = u8aConcat(u8aPrefix, u8a);
-
+
return base58Encode(u8aConcat(
input,
blake2AsU8a(input).subarray(0, [32, 33].includes(u8a.length) ? 2 : 1),
@@ -2556,7 +2556,7 @@
if (ethCrossAccount.sub === '0') {
return {Ethereum: ethCrossAccount.eth.toLocaleLowerCase()};
}
-
+
const ss58 = this.restoreCrossAccountFromBigInt(BigInt(ethCrossAccount.sub));
return {Substrate: ss58};
}
@@ -3074,14 +3074,14 @@
executeExtrinsic(sender: IKeyringPair, scheduledExtrinsic: string, scheduledParams: any[], expectSuccess?: boolean): Promise<ITransactionResult> {
const scheduledTx = this.constructApiCall(scheduledExtrinsic, scheduledParams);
-
+
const mandatorySchedArgs = [
this.blocksNum,
this.options.periodic ? [this.options.periodic.period, this.options.periodic.repetitions] : null,
this.options.priority ?? null,
scheduledTx,
];
-
+
let schedArgs;
let scheduleFn;
@@ -3301,7 +3301,7 @@
async getTokenPropertiesConsumedSpace(tokenId: number): Promise<number> {
const api = this.helper.getApi();
const props = (await api.query.nonfungible.tokenProperties(this.collectionId, tokenId)).toJSON();
-
+
return (props! as any).consumedSpace;
}
@@ -3419,7 +3419,7 @@
async getTokenPropertiesConsumedSpace(tokenId: number): Promise<number> {
const api = this.helper.getApi();
const props = (await api.query.refungible.tokenProperties(this.collectionId, tokenId)).toJSON();
-
+
return (props! as any).consumedSpace;
}
tests/src/vesting.test.tsdiffbeforeafterboth--- a/tests/src/vesting.test.ts
+++ b/tests/src/vesting.test.ts
@@ -73,7 +73,7 @@
expect(balanceRecepient.feeFrozen).to.eq(250n * nominal);
expect(balanceRecepient.miscFrozen).to.eq(250n * nominal);
expect(balanceRecepient.reserved).to.eq(0n);
-
+
// Wait first schedule ends and first part od second schedule:
await helper.wait.forRelayBlockNumber(SCHEDULE_2_START + SCHEDULE_2_PERIOD);
await helper.balance.claim(recepient);
@@ -84,7 +84,7 @@
expect(balanceRecepient.feeFrozen).to.eq(100n * nominal);
expect(balanceRecepient.miscFrozen).to.eq(100n * nominal);
expect(balanceRecepient.reserved).to.eq(0n);
-
+
// Schedules list contain 1 vesting:
schedule = await helper.balance.getVestingSchedules(recepient.address);
expect(schedule).to.has.length(1);
@@ -100,7 +100,7 @@
expect(balanceRecepient.feeFrozen).to.eq(0n);
expect(balanceRecepient.miscFrozen).to.eq(0n);
expect(balanceRecepient.reserved).to.eq(0n);
-
+
// check sender balance does not changed:
balanceSender = await helper.balance.getSubstrateFull(sender.address);
expect(balanceSender.free / nominal).to.eq(699n);
tests/src/xcm/xcmOpal.test.tsdiffbeforeafterboth--- a/tests/src/xcm/xcmOpal.test.ts
+++ b/tests/src/xcm/xcmOpal.test.ts
@@ -37,12 +37,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;
+const ASSET_AMOUNT = 1_000_000_000_000_000_000_000n;
describeXCM('[XCM] Integration test: Exchanging USDT with Westmint', () => {
let alice: IKeyringPair;
let bob: IKeyringPair;
-
+
let balanceStmnBefore: bigint;
let balanceStmnAfter: bigint;
@@ -66,7 +66,7 @@
await usingWestmintPlaygrounds(westmintUrl, async (helper) => {
// 350.00 (three hundred fifty) DOT
- const fundingAmount = 3_500_000_000_000n;
+ const fundingAmount = 3_500_000_000_000n;
await helper.assets.create(alice, ASSET_ID, alice.address, ASSET_METADATA_MINIMAL_BALANCE);
await helper.assets.setMetadata(alice, ASSET_ID, ASSET_METADATA_NAME, ASSET_METADATA_DESCRIPTION, ASSET_METADATA_DECIMALS);
@@ -151,7 +151,7 @@
await helper.xcm.limitedReserveTransferAssets(alice, destination, beneficiary, assets, feeAssetItem, 'Unlimited');
});
-
+
});
itSub('Should connect and send USDT from Westmint to Opal', async ({helper}) => {
@@ -190,7 +190,7 @@
},
{
GeneralIndex: ASSET_ID,
- },
+ },
]},
},
},
@@ -266,7 +266,7 @@
},
//10_000_000_000_000_000n,
TRANSFER_AMOUNT,
- ],
+ ],
[
{
NativeAssetId: 'Parent',
@@ -278,16 +278,16 @@
const feeItem = 1;
await helper.xTokens.transferMulticurrencies(alice, currencies, feeItem, destination, 'Unlimited');
-
+
// the commission has been paid in parachain native token
balanceOpalFinal = await helper.balance.getSubstrate(alice.address);
expect(balanceOpalAfter > balanceOpalFinal).to.be.true;
await usingWestmintPlaygrounds(westmintUrl, async (helper) => {
await helper.wait.newBlocks(3);
-
+
// The USDT token never paid fees. Its amount not changed from begin value.
- // Also check that xcm transfer has been succeeded
+ // Also check that xcm transfer has been succeeded
expect((await helper.assets.account(ASSET_ID, alice.address))! == ASSET_AMOUNT).to.be.true;
});
});
@@ -341,13 +341,13 @@
await helper.xcm.limitedReserveTransferAssets(bob, destination, beneficiary, assets, feeAssetItem, 'Unlimited');
});
-
+
await helper.wait.newBlocks(3);
- balanceBobAfter = await helper.balance.getSubstrate(bob.address);
+ balanceBobAfter = await helper.balance.getSubstrate(bob.address);
balanceBobRelayTokenAfter = await helper.tokens.accounts(bob.address, {NativeAssetId: 'Parent'});
- const wndFee = balanceBobRelayTokenAfter - TRANSFER_AMOUNT_RELAY - balanceBobRelayTokenBefore;
+ const wndFee = balanceBobRelayTokenAfter - TRANSFER_AMOUNT_RELAY - balanceBobRelayTokenBefore;
console.log(
'Relay (Westend) to Opal transaction fees: %s OPL',
helper.util.bigIntToDecimals(balanceBobAfter - balanceBobBefore),
tests/src/xcm/xcmQuartz.test.tsdiffbeforeafterboth--- a/tests/src/xcm/xcmQuartz.test.ts
+++ b/tests/src/xcm/xcmQuartz.test.ts
@@ -38,7 +38,7 @@
const TRANSFER_AMOUNT = 2000000000000000000000000n;
-const FUNDING_AMOUNT = 3_500_000_0000_000_000n;
+const FUNDING_AMOUNT = 3_500_000_0000_000_000n;
const TRANSFER_AMOUNT_RELAY = 50_000_000_000_000_000n;
@@ -52,7 +52,7 @@
describeXCM('[XCM] Integration test: Exchanging USDT with Statemine', () => {
let alice: IKeyringPair;
let bob: IKeyringPair;
-
+
let balanceStmnBefore: bigint;
let balanceStmnAfter: bigint;
@@ -81,7 +81,7 @@
});
await usingStateminePlaygrounds(statemineUrl, async (helper) => {
- const sovereignFundingAmount = 3_500_000_000n;
+ const sovereignFundingAmount = 3_500_000_000n;
await helper.assets.create(
alice,
@@ -185,7 +185,7 @@
await helper.xcm.limitedReserveTransferAssets(alice, destination, beneficiary, assets, feeAssetItem, 'Unlimited');
});
-
+
});
itSub('Should connect and send USDT from Statemine to Quartz', async ({helper}) => {
@@ -224,7 +224,7 @@
},
{
GeneralIndex: USDT_ASSET_ID,
- },
+ },
]},
},
},
@@ -267,7 +267,7 @@
console.log(
'[Statemine -> Quartz] transaction fees on Quartz: %s QTZ',
helper.util.bigIntToDecimals(balanceQuartzAfter - balanceQuartzBefore),
- );
+ );
// commission has not paid in USDT token
expect(free).to.be.equal(TRANSFER_AMOUNT);
// ... and parachain native token
@@ -299,7 +299,7 @@
ForeignAssetId: 0,
},
TRANSFER_AMOUNT,
- ],
+ ],
[
{
NativeAssetId: 'Parent',
@@ -311,7 +311,7 @@
const feeItem = 1;
await helper.xTokens.transferMulticurrencies(alice, currencies, feeItem, destination, 'Unlimited');
-
+
// the commission has been paid in parachain native token
balanceQuartzFinal = await helper.balance.getSubstrate(alice.address);
console.log('[Quartz -> Statemine] transaction fees on Quartz: %s QTZ', helper.util.bigIntToDecimals(balanceQuartzFinal - balanceQuartzAfter));
@@ -319,9 +319,9 @@
await usingStateminePlaygrounds(statemineUrl, async (helper) => {
await helper.wait.newBlocks(3);
-
+
// The USDT token never paid fees. Its amount not changed from begin value.
- // Also check that xcm transfer has been succeeded
+ // Also check that xcm transfer has been succeeded
expect((await helper.assets.account(USDT_ASSET_ID, alice.address))! == USDT_ASSET_AMOUNT).to.be.true;
});
});
@@ -372,10 +372,10 @@
await helper.xcm.limitedReserveTransferAssets(bob, destination, beneficiary, assets, feeAssetItem, 'Unlimited');
});
-
+
await helper.wait.newBlocks(3);
- balanceBobAfter = await helper.balance.getSubstrate(bob.address);
+ balanceBobAfter = await helper.balance.getSubstrate(bob.address);
balanceBobRelayTokenAfter = await helper.tokens.accounts(bob.address, {NativeAssetId: 'Parent'});
const wndFeeOnQuartz = balanceBobRelayTokenAfter - TRANSFER_AMOUNT_RELAY - balanceBobRelayTokenBefore;
tests/src/xcm/xcmUnique.test.tsdiffbeforeafterboth--- a/tests/src/xcm/xcmUnique.test.ts
+++ b/tests/src/xcm/xcmUnique.test.ts
@@ -38,7 +38,7 @@
const TRANSFER_AMOUNT = 2000000000000000000000000n;
-const FUNDING_AMOUNT = 3_500_000_0000_000_000n;
+const FUNDING_AMOUNT = 3_500_000_0000_000_000n;
const TRANSFER_AMOUNT_RELAY = 50_000_000_000_000_000n;
@@ -52,7 +52,7 @@
describeXCM('[XCM] Integration test: Exchanging USDT with Statemint', () => {
let alice: IKeyringPair;
let bob: IKeyringPair;
-
+
let balanceStmnBefore: bigint;
let balanceStmnAfter: bigint;
@@ -81,7 +81,7 @@
});
await usingStatemintPlaygrounds(statemintUrl, async (helper) => {
- const sovereignFundingAmount = 3_500_000_000n;
+ const sovereignFundingAmount = 3_500_000_000n;
await helper.assets.create(
alice,
@@ -185,7 +185,7 @@
await helper.xcm.limitedReserveTransferAssets(alice, destination, beneficiary, assets, feeAssetItem, 'Unlimited');
});
-
+
});
itSub('Should connect and send USDT from Statemint to Unique', async ({helper}) => {
@@ -224,7 +224,7 @@
},
{
GeneralIndex: USDT_ASSET_ID,
- },
+ },
]},
},
},
@@ -267,7 +267,7 @@
console.log(
'[Statemint -> Unique] transaction fees on Unique: %s UNQ',
helper.util.bigIntToDecimals(balanceUniqueAfter - balanceUniqueBefore),
- );
+ );
// commission has not paid in USDT token
expect(free).to.be.equal(TRANSFER_AMOUNT);
// ... and parachain native token
@@ -299,7 +299,7 @@
ForeignAssetId: 0,
},
TRANSFER_AMOUNT,
- ],
+ ],
[
{
NativeAssetId: 'Parent',
@@ -311,7 +311,7 @@
const feeItem = 1;
await helper.xTokens.transferMulticurrencies(alice, currencies, feeItem, destination, 'Unlimited');
-
+
// the commission has been paid in parachain native token
balanceUniqueFinal = await helper.balance.getSubstrate(alice.address);
console.log('[Unique -> Statemint] transaction fees on Unique: %s UNQ', helper.util.bigIntToDecimals(balanceUniqueFinal - balanceUniqueAfter));
@@ -319,9 +319,9 @@
await usingStatemintPlaygrounds(statemintUrl, async (helper) => {
await helper.wait.newBlocks(3);
-
+
// The USDT token never paid fees. Its amount not changed from begin value.
- // Also check that xcm transfer has been succeeded
+ // Also check that xcm transfer has been succeeded
expect((await helper.assets.account(USDT_ASSET_ID, alice.address))! == USDT_ASSET_AMOUNT).to.be.true;
});
});
@@ -372,10 +372,10 @@
await helper.xcm.limitedReserveTransferAssets(bob, destination, beneficiary, assets, feeAssetItem, 'Unlimited');
});
-
+
await helper.wait.newBlocks(3);
- balanceBobAfter = await helper.balance.getSubstrate(bob.address);
+ balanceBobAfter = await helper.balance.getSubstrate(bob.address);
balanceBobRelayTokenAfter = await helper.tokens.accounts(bob.address, {NativeAssetId: 'Parent'});
const wndFeeOnUnique = balanceBobRelayTokenAfter - TRANSFER_AMOUNT_RELAY - balanceBobRelayTokenBefore;
@@ -909,7 +909,7 @@
const unqRandomAccountAsset = await helper.assets.account(assetId, randomAccountMoonbeam.address);
expect(unqRandomAccountAsset).to.be.null;
-
+
balanceForeignUnqTokenFinal = 0n;
const unqOutcomeTransfer = balanceForeignUnqTokenMiddle - balanceForeignUnqTokenFinal;
tests/yarn.lockdiffbeforeafterboth--- a/tests/yarn.lock
+++ b/tests/yarn.lock
@@ -1065,7 +1065,7 @@
dependencies:
"@types/node" "*"
-"@typescript-eslint/eslint-plugin@^5.40.1":
+"@typescript-eslint/eslint-plugin@^5.47.0":
version "5.47.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.47.0.tgz#dadb79df3b0499699b155839fd6792f16897d910"
integrity sha512-AHZtlXAMGkDmyLuLZsRpH3p4G/1iARIwc/T0vIem2YB+xW6pZaXYXzCBnZSF/5fdM97R9QqZWZ+h3iW10XgevQ==
@@ -1080,7 +1080,7 @@
semver "^7.3.7"
tsutils "^3.21.0"
-"@typescript-eslint/parser@^5.40.1":
+"@typescript-eslint/parser@^5.47.0":
version "5.47.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.47.0.tgz#62e83de93499bf4b500528f74bf2e0554e3a6c8d"
integrity sha512-udPU4ckK+R1JWCGdQC4Qa27NtBg7w020ffHqGyAK8pAgOVuNw7YaKXGChk+udh+iiGIJf6/E/0xhVXyPAbsczw==