--- a/Cargo.lock +++ b/Cargo.lock @@ -4935,12 +4935,15 @@ name = "nft-data-structs" version = "0.9.0" dependencies = [ + "derivative", "frame-support", "frame-system", + "max-encoded-len", "parity-scale-codec", "serde", "sp-core", "sp-runtime", + "sp-std", ] [[package]] @@ -4999,6 +5002,7 @@ "cumulus-primitives-core", "cumulus-primitives-timestamp", "cumulus-primitives-utility", + "derivative", "fp-rpc", "frame-benchmarking", "frame-executive", @@ -5007,6 +5011,7 @@ "frame-system-benchmarking", "frame-system-rpc-runtime-api", "hex-literal", + "max-encoded-len", "nft-data-structs", "pallet-aura", "pallet-balances", @@ -5847,34 +5852,34 @@ [[package]] name = "pallet-scheduler" version = "3.0.0" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16" dependencies = [ "frame-benchmarking", "frame-support", "frame-system", "log", "parity-scale-codec", - "serde", - "sp-core", "sp-io", "sp-runtime", "sp-std", - "substrate-test-utils", - "up-sponsorship", ] [[package]] name = "pallet-scheduler" version = "3.0.0" -source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16" dependencies = [ "frame-benchmarking", "frame-support", "frame-system", "log", "parity-scale-codec", + "serde", + "sp-core", "sp-io", "sp-runtime", "sp-std", + "substrate-test-utils", + "up-sponsorship", ] [[package]] @@ -10690,13 +10695,13 @@ [[package]] name = "substrate-wasm-builder" version = "4.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93a3d51ad6abbc408b03ea962062bfcc959b438a318d7d4bedd181e1effd0610" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16" dependencies = [ "ansi_term 0.12.1", "atty", "build-helper", - "cargo_metadata 0.12.3", + "cargo_metadata 0.13.1", + "sp-maybe-compressed-blob", "tempfile", "toml", "walkdir", @@ -10706,13 +10711,13 @@ [[package]] name = "substrate-wasm-builder" version = "4.0.0" -source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93a3d51ad6abbc408b03ea962062bfcc959b438a318d7d4bedd181e1effd0610" dependencies = [ "ansi_term 0.12.1", "atty", "build-helper", - "cargo_metadata 0.13.1", - "sp-maybe-compressed-blob", + "cargo_metadata 0.12.3", "tempfile", "toml", "walkdir", --- a/crates/evm-coder-macros/src/solidity_interface.rs +++ b/crates/evm-coder-macros/src/solidity_interface.rs @@ -73,6 +73,20 @@ } } } + + fn expand_generator(&self) -> proc_macro2::TokenStream { + let pascal_call_name = &self.pascal_call_name; + quote! { + #pascal_call_name::generate_solidity_interface(out_set, is_impl); + } + } + + fn expand_event_generator(&self) -> proc_macro2::TokenStream { + let name = &self.name; + quote! { + #name::generate_solidity_interface(out_set, is_impl); + } + } } #[derive(Default)] @@ -109,12 +123,15 @@ struct MethodArg { name: Ident, + camel_name: String, ty: Ident, } impl MethodArg { fn try_from(value: &PatType) -> syn::Result { + let name = parse_ident_from_pat(&value.pat)?.clone(); Ok(Self { - name: parse_ident_from_pat(&value.pat)?.clone(), + camel_name: cases::camelcase::to_camel_case(&name.to_string()), + name, ty: parse_ident_from_type(&value.ty, false)?.clone(), }) } @@ -168,10 +185,10 @@ } fn expand_solidity_argument(&self) -> proc_macro2::TokenStream { - let name = &self.name.to_string(); + let camel_name = &self.camel_name.to_string(); let ty = &self.ty; quote! { - >::new(#name) + >::new(#camel_name) } } } @@ -397,7 +414,11 @@ }; let result = &self.result; - let args = self.args.iter().map(MethodArg::expand_solidity_argument); + let args = self + .args + .iter() + .filter(|a| !a.is_special()) + .map(MethodArg::expand_solidity_argument); quote! { SolidityFunction { @@ -475,6 +496,24 @@ let call_variants_this = self.methods.iter().map(Method::expand_variant_call); let solidity_functions = self.methods.iter().map(Method::expand_solidity_function); + // TODO: Inline inline_is + let solidity_is = self + .info + .is + .0 + .iter() + .chain(self.info.inline_is.0.iter()) + .map(|is| is.name.to_string()); + let solidity_events_is = self.info.events.0.iter().map(|is| is.name.to_string()); + let solidity_generators = self + .info + .is + .0 + .iter() + .chain(self.info.inline_is.0.iter()) + .map(Is::expand_generator); + let solidity_event_generators = self.info.events.0.iter().map(Is::expand_event_generator); + // let methods = self.methods.iter().map(Method::solidity_def); quote! { @@ -505,18 +544,40 @@ )* ) } - pub fn generate_solidity_interface() -> string { + pub fn generate_solidity_interface(out_set: &mut sp_std::collections::btree_set::BTreeSet, is_impl: bool) { use evm_coder::solidity::*; use core::fmt::Write; let interface = SolidityInterface { name: #solidity_name, + is: &["Dummy", #( + #solidity_is, + )* #( + #solidity_events_is, + )* ], functions: (#( #solidity_functions, )*), }; + if is_impl { + out_set.insert("// Common stubs holder\ncontract Dummy {\n\tuint8 dummy;\n\tstring stub_error = \"this contract is implemented in native\";\n}\n".into()); + } else { + out_set.insert("// Common stubs holder\ninterface Dummy {\n}\n".into()); + } + #( + #solidity_generators + )* + #( + #solidity_event_generators + )* + let mut out = string::new(); - let _ = interface.format(&mut out); - out + // In solidity interface usage (is) should be preceeded by interface definition + // This comment helps to sort it in a set + if #solidity_name.starts_with("Inline") { + out.push_str("// Inline\n"); + } + let _ = interface.format(is_impl, &mut out); + out_set.insert(out); } } impl ::evm_coder::Call for #call_name { --- a/crates/evm-coder-macros/src/to_log.rs +++ b/crates/evm-coder-macros/src/to_log.rs @@ -1,3 +1,4 @@ +use inflector::cases; use syn::{Data, DeriveInput, Field, Fields, Ident, Variant, spanned::Spanned}; use std::fmt::Write; use quote::quote; @@ -6,6 +7,7 @@ struct EventField { name: Ident, + camel_name: String, ty: Ident, indexed: bool, } @@ -24,10 +26,18 @@ } Ok(Self { name: name.to_owned(), + camel_name: cases::camelcase::to_camel_case(&name.to_string()), ty: ty.to_owned(), indexed, }) } + fn expand_solidity_argument(&self) -> proc_macro2::TokenStream { + let camel_name = &self.camel_name; + let ty = &self.ty; + quote! { + >::new(#camel_name) + } + } } struct Event { @@ -116,6 +126,21 @@ )*]; } } + + fn expand_solidity_function(&self) -> proc_macro2::TokenStream { + let name = self.name.to_string(); + let args = self.fields.iter().map(EventField::expand_solidity_argument); + quote! { + SolidityEvent { + name: #name, + args: ( + #( + #args, + )* + ), + } + } + } } pub struct Events { @@ -144,12 +169,30 @@ let consts = self.events.iter().map(Event::expand_consts); let serializers = self.events.iter().map(Event::expand_serializers); + let solidity_name = self.name.to_string(); + let solidity_functions = self.events.iter().map(Event::expand_solidity_function); quote! { impl #name { #( #consts )* + + pub fn generate_solidity_interface(out_set: &mut sp_std::collections::btree_set::BTreeSet, is_impl: bool) { + use evm_coder::solidity::*; + use core::fmt::Write; + let interface = SolidityInterface { + name: #solidity_name, + is: &[], + functions: (#( + #solidity_functions, + )*), + }; + let mut out = string::new(); + out.push_str("// Inline\n"); + let _ = interface.format(is_impl, &mut out); + out_set.insert(out); + } } #[automatically_derived] --- a/crates/evm-coder/src/abi.rs +++ b/crates/evm-coder/src/abi.rs @@ -19,11 +19,16 @@ #[derive(Clone)] pub struct AbiReader<'i> { buf: &'i [u8], + subresult_offset: usize, offset: usize, } impl<'i> AbiReader<'i> { pub fn new(buf: &'i [u8]) -> Self { - Self { buf, offset: 0 } + Self { + buf, + subresult_offset: 0, + offset: 0, + } } pub fn new_call(buf: &'i [u8]) -> Result<(u32, Self)> { if buf.len() < 4 { @@ -32,11 +37,18 @@ let mut method_id = [0; 4]; method_id.copy_from_slice(&buf[0..4]); - Ok((u32::from_be_bytes(method_id), Self { buf, offset: 4 })) + Ok(( + u32::from_be_bytes(method_id), + Self { + buf, + subresult_offset: 4, + offset: 4, + }, + )) } fn read_padleft(&mut self) -> Result<[u8; S]> { - if self.buf.len() - self.offset < 32 { + if self.buf.len() - self.offset < ABI_ALIGNMENT { return Err(Error::Error(ExitError::OutOfOffset)); } let mut block = [0; S]; @@ -79,6 +91,9 @@ } Ok(subresult.buf[subresult.offset..subresult.offset + length].into()) } + pub fn string(&mut self) -> Result { + string::from_utf8(self.bytes()?).map_err(|_| Error::Error(ExitError::InvalidRange)) + } pub fn uint32(&mut self) -> Result { Ok(u32::from_be_bytes(self.read_padleft()?)) @@ -103,9 +118,13 @@ fn subresult(&mut self) -> Result> { let offset = self.read_usize()?; + if offset + self.subresult_offset > self.buf.len() { + return Err(Error::Error(ExitError::InvalidRange)); + } Ok(AbiReader { buf: self.buf, - offset: offset + self.offset, + subresult_offset: offset + self.subresult_offset, + offset: offset + self.subresult_offset, }) } @@ -196,7 +215,7 @@ for (static_offset, part) in self.dynamic_part { let part_offset = self.static_part.len(); - let encoded_dynamic_offset = usize::to_be_bytes(part_offset - static_offset); + let encoded_dynamic_offset = usize::to_be_bytes(part_offset); self.static_part[static_offset + ABI_ALIGNMENT - encoded_dynamic_offset.len() ..static_offset + ABI_ALIGNMENT] .copy_from_slice(&encoded_dynamic_offset); @@ -226,6 +245,7 @@ impl_abi_readable!(H160, address); impl_abi_readable!(Vec, bytes); impl_abi_readable!(bool, bool); +impl_abi_readable!(string, string); pub trait AbiWrite { fn abi_write(&self, writer: &mut AbiWriter); @@ -285,3 +305,54 @@ writer }} } + +#[cfg(test)] +pub mod test { + use super::{AbiReader, AbiWriter}; + use hex_literal::hex; + + #[test] + fn dynamic_after_static() { + let mut encoder = AbiWriter::new(); + encoder.bool(&true); + encoder.string("test"); + let encoded = encoder.finish(); + + let mut encoder = AbiWriter::new(); + encoder.bool(&true); + // Offset to subresult + encoder.uint32(&(32 * 2)); + // Len of "test" + encoder.uint32(&4); + encoder.write_padright(&[b't', b'e', b's', b't']); + let alternative_encoded = encoder.finish(); + + assert_eq!(encoded, alternative_encoded); + + let mut decoder = AbiReader::new(&encoded); + assert_eq!(decoder.bool().unwrap(), true); + assert_eq!(decoder.string().unwrap(), "test"); + } + + #[test] + fn mint_sample() { + let (call, mut decoder) = AbiReader::new_call(&hex!( + " + 50bb4e7f + 000000000000000000000000ad2c0954693c2b5404b7e50967d3481bea432374 + 0000000000000000000000000000000000000000000000000000000000000001 + 0000000000000000000000000000000000000000000000000000000000000060 + 0000000000000000000000000000000000000000000000000000000000000008 + 5465737420555249000000000000000000000000000000000000000000000000 + " + )) + .unwrap(); + assert_eq!(call, 0x50bb4e7f); + assert_eq!( + format!("{:?}", decoder.address().unwrap()), + "0xad2c0954693c2b5404b7e50967d3481bea432374" + ); + assert_eq!(decoder.uint32().unwrap(), 1); + assert_eq!(decoder.string().unwrap(), "Test URI"); + } +} --- a/crates/evm-coder/src/solidity.rs +++ b/crates/evm-coder/src/solidity.rs @@ -6,37 +6,44 @@ pub trait SolidityTypeName: 'static { fn solidity_name(writer: &mut impl fmt::Write) -> fmt::Result; + fn solidity_default(writer: &mut impl fmt::Write) -> fmt::Result; fn is_void() -> bool { false } } macro_rules! solidity_type_name { - ($($ty:ident => $name:expr),* $(,)?) => { + ($($ty:ident => $name:literal = $default:literal),* $(,)?) => { $( impl SolidityTypeName for $ty { fn solidity_name(writer: &mut impl core::fmt::Write) -> core::fmt::Result { write!(writer, $name) } + fn solidity_default(writer: &mut impl core::fmt::Write) -> core::fmt::Result { + write!(writer, $default) + } } )* }; } solidity_type_name! { - uint8 => "uint8", - uint32 => "uint32", - uint128 => "uint128", - uint256 => "uint256", - address => "address", - string => "memory string", - bytes => "memory bytes", - bool => "bool", + uint8 => "uint8" = "0", + uint32 => "uint32" = "0", + uint128 => "uint128" = "0", + uint256 => "uint256" = "0", + address => "address" = "0x0000000000000000000000000000000000000000", + string => "string memory" = "\"\"", + bytes => "bytes memory" = "hex\"\"", + bool => "bool" = "false", } impl SolidityTypeName for void { fn solidity_name(_writer: &mut impl fmt::Write) -> fmt::Result { Ok(()) } + fn solidity_default(_writer: &mut impl fmt::Write) -> fmt::Result { + Ok(()) + } fn is_void() -> bool { true } @@ -44,6 +51,8 @@ pub trait SolidityArguments { fn solidity_name(&self, writer: &mut impl fmt::Write) -> fmt::Result; + fn solidity_get(&self, writer: &mut impl fmt::Write) -> fmt::Result; + fn solidity_default(&self, writer: &mut impl fmt::Write) -> fmt::Result; fn is_empty(&self) -> bool { self.len() == 0 } @@ -61,6 +70,12 @@ Ok(()) } } + fn solidity_get(&self, _writer: &mut impl fmt::Write) -> fmt::Result { + Ok(()) + } + fn solidity_default(&self, writer: &mut impl fmt::Write) -> fmt::Result { + T::solidity_default(writer) + } fn len(&self) -> usize { if T::is_void() { 0 @@ -87,6 +102,12 @@ Ok(()) } } + fn solidity_get(&self, writer: &mut impl fmt::Write) -> fmt::Result { + writeln!(writer, "\t\t{};", self.0) + } + fn solidity_default(&self, writer: &mut impl fmt::Write) -> fmt::Result { + T::solidity_default(writer) + } fn len(&self) -> usize { if T::is_void() { 0 @@ -100,6 +121,12 @@ fn solidity_name(&self, _writer: &mut impl fmt::Write) -> fmt::Result { Ok(()) } + fn solidity_get(&self, _writer: &mut impl fmt::Write) -> fmt::Result { + Ok(()) + } + fn solidity_default(&self, _writer: &mut impl fmt::Write) -> fmt::Result { + Ok(()) + } fn len(&self) -> usize { 0 } @@ -122,13 +149,43 @@ )* ); Ok(()) } + fn solidity_get(&self, writer: &mut impl fmt::Write) -> fmt::Result { + for_tuples!( #( + Tuple.solidity_get(writer)?; + )* ); + Ok(()) + } + fn solidity_default(&self, writer: &mut impl fmt::Write) -> fmt::Result { + if self.is_empty() { + Ok(()) + } else if self.len() == 1 { + for_tuples!( #( + Tuple.solidity_default(writer)?; + )* ); + Ok(()) + } else { + write!(writer, "(")?; + let mut first = true; + for_tuples!( #( + if !Tuple.is_empty() { + if !first { + write!(writer, ", ")?; + } + first = false; + Tuple.solidity_name(writer)?; + } + )* ); + write!(writer, ")")?; + Ok(()) + } + } fn len(&self) -> usize { for_tuples!( #( Tuple.len() )+* ) } } pub trait SolidityFunctions { - fn solidity_name(&self, writer: &mut impl fmt::Write) -> fmt::Result; + fn solidity_name(&self, is_impl: bool, writer: &mut impl fmt::Write) -> fmt::Result; } pub enum SolidityMutability { @@ -143,10 +200,15 @@ pub mutability: SolidityMutability, } impl SolidityFunctions for SolidityFunction { - fn solidity_name(&self, writer: &mut impl fmt::Write) -> fmt::Result { - write!(writer, "function {}(", self.name)?; + fn solidity_name(&self, is_impl: bool, writer: &mut impl fmt::Write) -> fmt::Result { + write!(writer, "\tfunction {}(", self.name)?; self.args.solidity_name(writer)?; - write!(writer, ") external")?; + write!(writer, ")")?; + if is_impl { + write!(writer, " public")?; + } else { + write!(writer, " external")?; + } match &self.mutability { SolidityMutability::Pure => write!(writer, " pure")?, SolidityMutability::View => write!(writer, " view")?, @@ -157,7 +219,25 @@ self.result.solidity_name(writer)?; write!(writer, ")")?; } - writeln!(writer, ";") + if is_impl { + writeln!(writer, " {{")?; + writeln!(writer, "\t\trequire(false, stub_error);")?; + self.args.solidity_get(writer)?; + match &self.mutability { + SolidityMutability::Pure => {} + SolidityMutability::View => writeln!(writer, "\t\tdummy;")?, + SolidityMutability::Mutable => writeln!(writer, "\t\tdummy = 0;")?, + } + if !self.result.is_empty() { + write!(writer, "\t\treturn ")?; + self.result.solidity_default(writer)?; + writeln!(writer, ";")?; + } + writeln!(writer, "\t}}")?; + } else { + writeln!(writer, ";")?; + } + Ok(()) } } @@ -165,10 +245,10 @@ impl SolidityFunctions for Tuple { for_tuples!( where #( Tuple: SolidityFunctions ),* ); - fn solidity_name(&self, writer: &mut impl fmt::Write) -> fmt::Result { + fn solidity_name(&self, is_impl: bool, writer: &mut impl fmt::Write) -> fmt::Result { let mut first = false; for_tuples!( #( - Tuple.solidity_name(writer)?; + Tuple.solidity_name(is_impl, writer)?; )* ); Ok(()) } @@ -176,14 +256,43 @@ pub struct SolidityInterface { pub name: &'static str, + pub is: &'static [&'static str], pub functions: F, } impl SolidityInterface { - pub fn format(&self, out: &mut impl fmt::Write) -> fmt::Result { - writeln!(out, "interface {} {{", self.name)?; - self.functions.solidity_name(out)?; + pub fn format(&self, is_impl: bool, out: &mut impl fmt::Write) -> fmt::Result { + if is_impl { + write!(out, "contract ")?; + } else { + write!(out, "interface ")?; + } + write!(out, "{}", self.name)?; + if !self.is.is_empty() { + write!(out, " is")?; + for (i, n) in self.is.iter().enumerate() { + if i != 0 { + write!(out, ",")?; + } + write!(out, " {}", n)?; + } + } + writeln!(out, " {{")?; + self.functions.solidity_name(is_impl, out)?; writeln!(out, "}}")?; Ok(()) } } + +pub struct SolidityEvent { + pub name: &'static str, + pub args: A, +} + +impl SolidityFunctions for SolidityEvent { + fn solidity_name(&self, _is_impl: bool, writer: &mut impl fmt::Write) -> fmt::Result { + write!(writer, "\tevent {}(", self.name)?; + self.args.solidity_name(writer)?; + writeln!(writer, ");") + } +} --- a/node/cli/src/chain_spec.rs +++ b/node/cli/src/chain_spec.rs @@ -202,18 +202,6 @@ nft_item_id: vec![], fungible_item_id: vec![], refungible_item_id: vec![], - chain_limit: ChainLimits { - collection_numbers_limit: 100000, - account_token_ownership_limit: 1000000, - collections_admins_limit: 5, - custom_data_limit: 2048, - nft_sponsor_transfer_timeout: 15, - fungible_sponsor_transfer_timeout: 15, - refungible_sponsor_transfer_timeout: 15, - offchain_schema_limit: 1024, - variable_on_chain_schema_limit: 1024, - const_on_chain_schema_limit: 1024, - }, }, parachain_info: nft_runtime::ParachainInfoConfig { parachain_id: id }, aura: nft_runtime::AuraConfig { --- a/pallets/nft/Cargo.toml +++ b/pallets/nft/Cargo.toml @@ -41,6 +41,7 @@ 'evm-coder/std', 'pallet-evm-coder-substrate/std', ] +limit-testing = ["nft-data-structs/limit-testing"] ################################################################################ # Substrate Dependencies --- a/pallets/nft/src/default_weights.rs +++ b/pallets/nft/src/default_weights.rs @@ -117,11 +117,6 @@ .saturating_add(DbWeight::get().reads(2_u64)) .saturating_add(DbWeight::get().writes(1_u64)) } - fn set_chain_limits() -> Weight { - 1_300_000_u64 - .saturating_add(DbWeight::get().reads(0_u64)) - .saturating_add(DbWeight::get().writes(1_u64)) - } fn set_contract_sponsoring_rate_limit() -> Weight { 3_500_000_u64 .saturating_add(DbWeight::get().reads(0_u64)) --- a/pallets/nft/src/eth/erc.rs +++ b/pallets/nft/src/eth/erc.rs @@ -1,12 +1,15 @@ use core::char::{decode_utf16, REPLACEMENT_CHARACTER}; use evm_coder::{ToLog, execution::Result, solidity, solidity_interface, types::*}; +use nft_data_structs::{CreateItemData, CreateNftData}; use core::convert::TryInto; -use alloc::format; -use crate::{Allowances, Module, Balance, CollectionHandle, CollectionMode, Config, NftItemList}; -use frame_support::storage::StorageDoubleMap; +use crate::{ + Allowances, Module, Balance, CollectionHandle, CollectionMode, Config, NftItemList, + ItemListIndex, +}; +use frame_support::storage::{StorageMap, StorageDoubleMap}; use pallet_evm::AddressMapping; use super::account::CrossAccountId; -use sp_std::vec::Vec; +use sp_std::{vec, vec::Vec}; #[solidity_interface(name = "ERC165")] impl CollectionHandle { @@ -42,9 +45,15 @@ #[solidity_interface(name = "ERC721Metadata", inline_is(InlineNameSymbol))] impl CollectionHandle { + #[solidity(rename_selector = "tokenURI")] fn token_uri(&self, token_id: uint256) -> Result { - // TODO: We should standartize url prefix, maybe via offchain schema? - Ok(format!("unique.network/{}/{}", self.id, token_id)) + let token_id: u32 = token_id.try_into().map_err(|_| "token id overflow")?; + Ok(string::from_utf8_lossy( + &>::get(self.id, token_id) + .ok_or("token not found")? + .const_data, + ) + .into()) } } @@ -178,6 +187,93 @@ } } +#[solidity_interface(name = "ERC721Burnable")] +impl CollectionHandle { + fn burn(&mut self, caller: caller, token_id: uint256) -> Result { + let caller = T::CrossAccountId::from_eth(caller); + let token_id = token_id.try_into().map_err(|_| "amount overflow")?; + + >::burn_item_internal(&caller, &self, token_id, 1).map_err(|_| "burn error")?; + Ok(()) + } +} + +#[derive(ToLog)] +pub enum ERC721MintableEvents { + #[allow(dead_code)] + MintingFinished {}, +} + +#[solidity_interface(name = "ERC721Mintable", events(ERC721MintableEvents))] +impl CollectionHandle { + fn minting_finished(&self) -> Result { + Ok(false) + } + + fn mint(&mut self, caller: caller, to: address, token_id: uint256) -> Result { + let caller = T::CrossAccountId::from_eth(caller); + let to = T::CrossAccountId::from_eth(to); + let token_id: u32 = token_id.try_into().map_err(|_| "amount overflow")?; + if ::get(self.id) + .checked_add(1) + .ok_or("item id overflow")? + != token_id + { + return Err("item id should be next".into()); + } + + >::create_item_internal( + &caller, + &self, + &to, + CreateItemData::NFT(CreateNftData { + const_data: vec![].try_into().unwrap(), + variable_data: vec![].try_into().unwrap(), + }), + ) + .map_err(|_| "mint error")?; + Ok(true) + } + + #[solidity(rename_selector = "mintWithTokenURI")] + fn mint_with_token_uri( + &mut self, + caller: caller, + to: address, + token_id: uint256, + token_uri: string, + ) -> Result { + let caller = T::CrossAccountId::from_eth(caller); + let to = T::CrossAccountId::from_eth(to); + let token_id: u32 = token_id.try_into().map_err(|_| "amount overflow")?; + if ::get(self.id) + .checked_add(1) + .ok_or("item id overflow")? + != token_id + { + return Err("item id should be next".into()); + } + + >::create_item_internal( + &caller, + &self, + &to, + CreateItemData::NFT(CreateNftData { + const_data: Vec::::from(token_uri) + .try_into() + .map_err(|_| "token uri is too long")?, + variable_data: vec![].try_into().unwrap(), + }), + ) + .map_err(|_| "mint error")?; + Ok(true) + } + + fn finish_minting(&mut self, _caller: caller) -> Result { + Err("not implementable".into()) + } +} + #[solidity_interface(name = "ERC721UniqueExtensions")] impl CollectionHandle { #[solidity(rename_selector = "transfer")] @@ -196,6 +292,13 @@ .map_err(|_| "transfer error")?; Ok(()) } + + fn next_token_id(&self) -> Result { + Ok(ItemListIndex::get(self.id) + .checked_add(1) + .ok_or("item id overflow")? + .into()) + } } #[solidity_interface( @@ -205,7 +308,9 @@ ERC721, ERC721Metadata, ERC721Enumerable, - ERC721UniqueExtensions + ERC721UniqueExtensions, + ERC721Mintable, + ERC721Burnable, ) )] impl CollectionHandle {} @@ -297,3 +402,32 @@ #[solidity_interface(name = "UniqueFungible", is(ERC165, ERC20))] impl CollectionHandle {} + +macro_rules! generate_code { + ($name:ident, $decl:ident, $is_impl:literal) => { + #[test] + #[ignore] + fn $name() { + use sp_std::collections::btree_set::BTreeSet; + let mut out = BTreeSet::new(); + $decl::generate_solidity_interface(&mut out, $is_impl); + println!("=== SNIP START ==="); + println!("// SPDX-License-Identifier: OTHER"); + println!("// This code is automatically generated with `cargo test --package pallet-nft -- eth::erc::{} --exact --nocapture --ignored`", stringify!(name)); + println!(); + println!("pragma solidity >=0.8.0 <0.9.0;"); + println!(); + for b in out { + println!("{}", b); + } + println!("=== SNIP END ==="); + } + }; +} + +// Not a tests, but code generators +generate_code!(nft_impl, UniqueNFTCall, true); +generate_code!(nft_iface, UniqueNFTCall, false); + +generate_code!(fungible_impl, UniqueFungibleCall, true); +generate_code!(fungible_iface, UniqueFungibleCall, false); --- a/pallets/nft/src/eth/sponsoring.rs +++ b/pallets/nft/src/eth/sponsoring.rs @@ -1,12 +1,12 @@ //! Implements EVM sponsoring logic via OnChargeEVMTransaction use crate::{ - ChainLimit, Collection, CollectionById, Config, FungibleTransferBasket, NftTransferBasket, + Collection, CollectionById, Config, FungibleTransferBasket, NftTransferBasket, eth::{account::EvmBackwardsAddressMapping, map_eth_to_id}, }; use evm_coder::{Call, abi::AbiReader}; use frame_support::{ - storage::{StorageMap, StorageDoubleMap, StorageValue}, + storage::{StorageMap, StorageDoubleMap}, }; use sp_core::H160; use sp_std::prelude::*; @@ -17,6 +17,7 @@ }; use core::convert::TryInto; use core::marker::PhantomData; +use nft_data_structs::{NFT_SPONSOR_TRANSFER_TIMEOUT, FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT}; struct AnyError; @@ -43,7 +44,7 @@ let limit: u32 = if collection_limits.sponsor_transfer_timeout > 0 { collection_limits.sponsor_transfer_timeout } else { - ChainLimit::get().nft_sponsor_transfer_timeout + NFT_SPONSOR_TRANSFER_TIMEOUT }; let mut sponsor = true; @@ -74,7 +75,7 @@ let limit: u32 = if collection_limits.sponsor_transfer_timeout > 0 { collection_limits.sponsor_transfer_timeout } else { - ChainLimit::get().fungible_sponsor_transfer_timeout + FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT }; let block_number = >::block_number() as T::BlockNumber; --- a/pallets/nft/src/eth/stubs/ERC20.sol +++ b/pallets/nft/src/eth/stubs/ERC20.sol @@ -1,69 +1,94 @@ // SPDX-License-Identifier: OTHER +// This code is automatically generated with `cargo test --package pallet-nft -- eth::erc::name --exact --nocapture --ignored` pragma solidity >=0.8.0 <0.9.0; -contract ERC20 { - uint8 _dummy = 0; - string stub_error = "this contract does not exists, code for collections is implemented at pallet side"; +// Common stubs holder +contract Dummy { + uint8 dummy; + string stub_error = "this contract is implemented in native"; +} - // 0x18160ddd - function totalSupply() external view returns (uint256) { +// Inline +contract ERC20Events { + event Transfer(address from, address to, uint256 value); + event Approval(address owner, address spender, uint256 value); +} + +// Inline +contract InlineNameSymbol is Dummy { + function name() public view returns (string memory) { require(false, stub_error); - _dummy; - return 0; + dummy; + return ""; } + function symbol() public view returns (string memory) { + require(false, stub_error); + dummy; + return ""; + } +} - // 0x70a08231 - function balanceOf(address account) external view returns (uint256) { +// Inline +contract InlineTotalSupply is Dummy { + function totalSupply() public view returns (uint256) { require(false, stub_error); - account; - _dummy; + dummy; return 0; } +} - // 0xa9059cbb - function transfer(address recipient, uint256 amount) external returns (bool) { +contract ERC165 is Dummy { + function supportsInterface(uint32 interfaceId) public view returns (bool) { require(false, stub_error); - recipient; - amount; - _dummy = 0; + interfaceId; + dummy; return false; } +} - // 0xdd62ed3e - function allowance(address owner, address spender) external view returns (uint256) { +contract ERC20 is Dummy, InlineNameSymbol, InlineTotalSupply, ERC20Events { + function decimals() public view returns (uint8) { require(false, stub_error); + dummy; + return 0; + } + function balanceOf(address owner) public view returns (uint256) { + require(false, stub_error); owner; - spender; - return _dummy; + dummy; + return 0; + } + function transfer(address to, uint256 amount) public returns (bool) { + require(false, stub_error); + to; + amount; + dummy = 0; + return false; } - - // 0x095ea7b3 - function approve(address spender, uint256 amount) external returns (bool) { + function transferFrom(address from, address to, uint256 amount) public returns (bool) { require(false, stub_error); - spender; + from; + to; amount; - _dummy = 0; + dummy = 0; return false; } - - // 0x23b872dd - function transferFrom(address sender, address recipient, uint256 amount) external returns (bool) { + function approve(address spender, uint256 amount) public returns (bool) { require(false, stub_error); - sender; - recipient; + spender; amount; - _dummy = 0; + dummy = 0; return false; } + function allowance(address owner, address spender) public view returns (uint256) { + require(false, stub_error); + owner; + spender; + dummy; + return 0; + } +} - // While ERC165 is not required by spec of ERC20, better implement it - // 0x01ffc9a7 - function supportsInterface(bytes4 interfaceID) public pure returns (bool) { - return - // ERC20 - interfaceID == 0x36372b07 || - // ERC165 - interfaceID == 0x01ffc9a7; - } +contract UniqueFungible is Dummy, ERC165, ERC20 { } \ No newline at end of file --- a/pallets/nft/src/eth/stubs/ERC721.sol +++ b/pallets/nft/src/eth/stubs/ERC721.sol @@ -1,163 +1,194 @@ // SPDX-License-Identifier: OTHER +// This code is automatically generated with `cargo test --package pallet-nft -- eth::erc::name --exact --nocapture --ignored` pragma solidity >=0.8.0 <0.9.0; -contract ERC721 { - uint8 _dummy = 0; - address _dummy_addr = 0x0000000000000000000000000000000000000000; - string _dummy_string = ""; - string stub_error = - "this contract does not exists, code for collections is implemented at pallet side"; +// Common stubs holder +contract Dummy { + uint8 dummy; + string stub_error = "this contract is implemented in native"; +} - event Transfer( - address indexed from, - address indexed to, - uint256 indexed tokenId - ); +// Inline +contract ERC721Events { + event Transfer(address from, address to, uint256 tokenId); + event Approval(address owner, address approved, uint256 tokenId); + event ApprovalForAll(address owner, address operator, bool approved); +} - event Approval( - address indexed owner, - address indexed approved, - uint256 indexed tokenId - ); +// Inline +contract ERC721MintableEvents { + event MintingFinished(); +} - event ApprovalForAll( - address indexed owner, - address indexed operator, - bool approved - ); +// Inline +contract InlineNameSymbol is Dummy { + function name() public view returns (string memory) { + require(false, stub_error); + dummy; + return ""; + } + function symbol() public view returns (string memory) { + require(false, stub_error); + dummy; + return ""; + } +} - // 0x18160ddd - function totalSupply() external view returns (uint256) { - require(false, stub_error); - return 0; - } +// Inline +contract InlineTotalSupply is Dummy { + function totalSupply() public view returns (uint256) { + require(false, stub_error); + dummy; + return 0; + } +} - function name() external view returns (string memory res_name) { - require(false, stub_error); - res_name = _dummy_string; - } +contract ERC165 is Dummy { + function supportsInterface(uint32 interfaceId) public view returns (bool) { + require(false, stub_error); + interfaceId; + dummy; + return false; + } +} - function symbol() external view returns (string memory res_symbol) { - require(false, stub_error); - res_symbol = _dummy_string; - } +contract ERC721 is Dummy, ERC165, ERC721Events { + function balanceOf(address owner) public view returns (uint256) { + require(false, stub_error); + owner; + dummy; + return 0; + } + function ownerOf(uint256 tokenId) public view returns (address) { + require(false, stub_error); + tokenId; + dummy; + return 0x0000000000000000000000000000000000000000; + } + function safeTransferFromWithData(address from, address to, uint256 tokenId, bytes memory data) public { + require(false, stub_error); + from; + to; + tokenId; + data; + dummy = 0; + } + function safeTransferFrom(address from, address to, uint256 tokenId) public { + require(false, stub_error); + from; + to; + tokenId; + dummy = 0; + } + function transferFrom(address from, address to, uint256 tokenId) public { + require(false, stub_error); + from; + to; + tokenId; + dummy = 0; + } + function approve(address approved, uint256 tokenId) public { + require(false, stub_error); + approved; + tokenId; + dummy = 0; + } + function setApprovalForAll(address operator, bool approved) public { + require(false, stub_error); + operator; + approved; + dummy = 0; + } + function getApproved(uint256 tokenId) public view returns (address) { + require(false, stub_error); + tokenId; + dummy; + return 0x0000000000000000000000000000000000000000; + } + function isApprovedForAll(address owner, address operator) public view returns (address) { + require(false, stub_error); + owner; + operator; + dummy; + return 0x0000000000000000000000000000000000000000; + } +} - function tokenURI(uint256 tokenId) external view returns (string memory) { - require(false, stub_error); - tokenId; - return _dummy_string; - } +contract ERC721Burnable is Dummy { + function burn(uint256 tokenId) public { + require(false, stub_error); + tokenId; + dummy = 0; + } +} - function tokenByIndex(uint256 index) external view returns (uint256) { - require(false, stub_error); - index; +contract ERC721Enumerable is Dummy, InlineTotalSupply { + function tokenByIndex(uint256 index) public view returns (uint256) { + require(false, stub_error); + index; + dummy; return 0; - } - - function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256) { - require(false, stub_error); + } + function tokenOfOwnerByIndex(address owner, uint256 index) public view returns (uint256) { + require(false, stub_error); owner; index; + dummy; return 0; - } + } +} - // 0x70a08231 - function balanceOf(address owner) external view returns (uint256) { - require(false, stub_error); - owner; - return 0; - } +contract ERC721Metadata is Dummy, InlineNameSymbol { + function tokenURI(uint256 tokenId) public view returns (string memory) { + require(false, stub_error); + tokenId; + dummy; + return ""; + } +} - // 0x6352211e - function ownerOf(uint256 tokenId) external view returns (address) { - require(false, stub_error); - tokenId; - return _dummy_addr; - } +contract ERC721Mintable is Dummy, ERC721MintableEvents { + function mintingFinished() public view returns (bool) { + require(false, stub_error); + dummy; + return false; + } + function mint(address to, uint256 tokenId) public returns (bool) { + require(false, stub_error); + to; + tokenId; + dummy = 0; + return false; + } + function mintWithTokenURI(address to, uint256 tokenId, string memory tokenUri) public returns (bool) { + require(false, stub_error); + to; + tokenId; + tokenUri; + dummy = 0; + return false; + } + function finishMinting() public returns (bool) { + require(false, stub_error); + dummy = 0; + return false; + } +} - // 0xb88d4fde - function safeTransferFrom( - address from, - address to, - uint256 tokenId, - bytes calldata data - ) external payable { - require(false, stub_error); - from; - to; - tokenId; - data; - } - - // 0x42842e0e - function safeTransferFrom( - address from, - address to, - uint256 tokenId - ) external payable { - require(false, stub_error); - from; - to; - tokenId; - } - - // 0x23b872dd - function transferFrom( - address from, - address to, - uint256 tokenId - ) external payable { - require(false, stub_error); - from; - to; - tokenId; - } +contract ERC721UniqueExtensions is Dummy { + function transfer(address to, uint256 tokenId) public { + require(false, stub_error); + to; + tokenId; + dummy = 0; + } + function nextTokenId() public view returns (uint256) { + require(false, stub_error); + dummy; + return 0; + } +} - // 0x095ea7b3 - function approve(address approved, uint256 tokenId) external payable { - require(false, stub_error); - approved; - tokenId; - } - - // 0xa22cb465 - function setApprovalForAll(address operator, bool approved) external { - require(false, stub_error); - operator; - approved; - _dummy = 0; - } - - // 0x081812fc - function getApproved(uint256 tokenId) external view returns (address) { - require(false, stub_error); - tokenId; - return _dummy_addr; - } - - // 0xe985e9c5 - function isApprovedForAll(address owner, address operator) - external - view - returns (bool) - { - require(false, stub_error); - owner; - operator; - return false; - } - - // 0x01ffc9a7 - function supportsInterface(bytes4 interfaceID) public pure returns (bool) { - return - // ERC721 - interfaceID == 0x80ac58cd || - // ERC721Metadata - interfaceID == 0x5b5e139f || - // ERC721Enumerable - interfaceID == 0x780e9d63 || - // ERC165 - interfaceID == 0x01ffc9a7; - } -} +contract UniqueNFT is Dummy, ERC165, ERC721, ERC721Metadata, ERC721Enumerable, ERC721UniqueExtensions, ERC721Mintable, ERC721Burnable { +} \ No newline at end of file --- a/pallets/nft/src/lib.rs +++ b/pallets/nft/src/lib.rs @@ -31,14 +31,16 @@ StorageValue, transactional, }; -use frame_system::{self as system, ensure_signed, ensure_root}; +use frame_system::{self as system, ensure_signed}; use sp_core::H160; use sp_std::vec; -use sp_runtime::sp_std::prelude::Vec; +use sp_runtime::{DispatchError, sp_std::prelude::Vec}; use core::ops::{Deref, DerefMut}; use nft_data_structs::{ MAX_DECIMAL_POINTS, MAX_SPONSOR_TIMEOUT, MAX_TOKEN_OWNERSHIP, MAX_REFUNGIBLE_PIECES, - AccessMode, ChainLimits, Collection, CreateItemData, CollectionLimits, CollectionId, + CUSTOM_DATA_LIMIT, COLLECTION_NUMBER_LIMIT, ACCOUNT_TOKEN_OWNERSHIP_LIMIT, + VARIABLE_ON_CHAIN_SCHEMA_LIMIT, CONST_ON_CHAIN_SCHEMA_LIMIT, COLLECTION_ADMINS_LIMIT, + OFFCHAIN_SCHEMA_LIMIT, AccessMode, Collection, CreateItemData, CollectionLimits, CollectionId, CollectionMode, TokenId, SchemaVersion, SponsorshipState, Ownership, NftItemType, FungibleItemType, ReFungibleItemType, }; @@ -86,7 +88,6 @@ fn set_variable_meta_data() -> Weight; fn enable_contract_sponsoring() -> Weight; fn set_schema_version() -> Weight; - fn set_chain_limits() -> Weight; fn set_contract_sponsoring_rate_limit() -> Weight; fn set_variable_meta_data_sponsoring_rate_limit() -> Weight; fn toggle_contract_white_list() -> Weight; @@ -176,6 +177,8 @@ OutOfGas, /// Collection settings not allowing items transferring TransferNotAllowed, + /// Can't transfer tokens to ethereum zero address + AddressIsZero, } } @@ -202,9 +205,16 @@ pub fn log(&self, log: impl evm_coder::ToLog) -> DispatchResult { self.recorder.log_sub(log) } + #[allow(dead_code)] fn consume_gas(&self, gas: u64) -> DispatchResult { self.recorder.consume_gas_sub(gas) } + fn consume_sload(&self) -> DispatchResult { + self.recorder.consume_sload_sub() + } + fn consume_sstore(&self) -> DispatchResult { + self.recorder.consume_sstore_sub() + } pub fn submit_logs(self) -> DispatchResult { self.recorder.submit_logs() } @@ -278,10 +288,6 @@ /// Id of last collection token /// Collection id (controlled?1) ItemListIndex: map hasher(blake2_128_concat) CollectionId => TokenId; - //#endregion - - //#region Chain limits struct - pub ChainLimit get(fn chain_limit) config(): ChainLimits; //#endregion //#region Bound counters @@ -435,6 +441,7 @@ origin: T::Origin { fn deposit_event() = default; + const CollectionAdminsLimit: u64 = COLLECTION_ADMINS_LIMIT; type Error = Error; fn on_initialize(_now: T::BlockNumber) -> Weight { @@ -485,14 +492,12 @@ CollectionMode::Fungible(points) => points, _ => 0 }; - - let chain_limit = ChainLimit::get(); let created_count = CreatedCollectionCount::get(); let destroyed_count = DestroyedCollectionCount::get(); // bound Total number of collections - ensure!(created_count - destroyed_count < chain_limit.collection_numbers_limit, Error::::TotalCollectionsLimitExceeded); + ensure!(created_count - destroyed_count < COLLECTION_NUMBER_LIMIT, Error::::TotalCollectionsLimitExceeded); // check params ensure!(decimal_points <= MAX_DECIMAL_POINTS, Error::::CollectionDecimalPointLimitExceeded); @@ -508,7 +513,7 @@ CreatedCollectionCount::put(next_id); let limits = CollectionLimits { - sponsored_data_size: chain_limit.custom_data_limit, + sponsored_data_size: CUSTOM_DATA_LIMIT, ..Default::default() }; @@ -737,8 +742,7 @@ match admin_arr.binary_search(&new_admin_id) { Ok(_) => {}, Err(idx) => { - let limits = ChainLimit::get(); - ensure!(admin_arr.len() < limits.collections_admins_limit as usize, Error::::CollectionAdminsLimitExceeded); + ensure!(admin_arr.len() < COLLECTION_ADMINS_LIMIT as usize, Error::::CollectionAdminsLimitExceeded); admin_arr.insert(idx, new_admin_id); >::insert(collection_id, admin_arr); } @@ -1138,7 +1142,7 @@ Self::check_owner_or_admin_permissions(&target_collection, &sender)?; // check schema limit - ensure!(schema.len() as u32 <= ChainLimit::get().offchain_schema_limit, ""); + ensure!(schema.len() as u32 <= OFFCHAIN_SCHEMA_LIMIT, ""); target_collection.offchain_schema = schema; target_collection.save() @@ -1168,7 +1172,7 @@ Self::check_owner_or_admin_permissions(&target_collection, &sender)?; // check schema limit - ensure!(schema.len() as u32 <= ChainLimit::get().const_on_chain_schema_limit, ""); + ensure!(schema.len() as u32 <= CONST_ON_CHAIN_SCHEMA_LIMIT, ""); target_collection.const_on_chain_schema = schema; target_collection.save() @@ -1198,27 +1202,12 @@ Self::check_owner_or_admin_permissions(&target_collection, &sender)?; // check schema limit - ensure!(schema.len() as u32 <= ChainLimit::get().variable_on_chain_schema_limit, ""); + ensure!(schema.len() as u32 <= VARIABLE_ON_CHAIN_SCHEMA_LIMIT, ""); target_collection.variable_on_chain_schema = schema; target_collection.save() } - // Sudo permissions function - #[weight = ::WeightInfo::set_chain_limits()] - #[transactional] - pub fn set_chain_limits( - origin, - limits: ChainLimits - ) -> DispatchResult { - - #[cfg(not(feature = "runtime-benchmarks"))] - ensure_root(origin)?; - - ::put(limits); - Ok(()) - } - #[weight = ::WeightInfo::set_collection_limits()] #[transactional] pub fn set_collection_limits( @@ -1230,12 +1219,11 @@ let mut target_collection = Self::get_collection(collection_id)?; Self::check_owner_permissions(&target_collection, sender.as_sub())?; let old_limits = &target_collection.limits; - let chain_limits = ChainLimit::get(); // collection bounds ensure!(new_limits.sponsor_transfer_timeout <= MAX_SPONSOR_TIMEOUT && new_limits.account_token_ownership_limit <= MAX_TOKEN_OWNERSHIP && - new_limits.sponsored_data_size <= chain_limits.custom_data_limit, + new_limits.sponsored_data_size <= CUSTOM_DATA_LIMIT, Error::::CollectionLimitBoundsExceeded); // token_limit check prev @@ -1262,6 +1250,11 @@ owner: &T::CrossAccountId, data: CreateItemData, ) -> DispatchResult { + ensure!( + owner != &T::CrossAccountId::from_eth(H160([0; 20])), + Error::::AddressIsZero + ); + Self::can_create_items_in_collection(collection, sender, owner, 1)?; Self::validate_create_item_args(collection, &data)?; Self::create_item_no_validation(collection, owner, data)?; @@ -1276,14 +1269,18 @@ item_id: TokenId, value: u128, ) -> DispatchResult { - target_collection.consume_gas(2000000)?; + ensure!( + recipient != &T::CrossAccountId::from_eth(H160([0; 20])), + Error::::AddressIsZero + ); + // Limits check Self::is_correct_transfer(target_collection, recipient)?; // Transfer permissions check ensure!( - Self::is_item_owner(sender, target_collection, item_id) - || Self::is_owner_or_admin_permissions(target_collection, sender), + Self::is_item_owner(sender, target_collection, item_id)? + || Self::is_owner_or_admin_permissions(target_collection, sender)?, Error::::NoPermission ); @@ -1330,16 +1327,15 @@ item_id: TokenId, amount: u128, ) -> DispatchResult { - collection.consume_gas(2000000)?; Self::token_exists(collection, item_id)?; // Transfer permissions check let bypasses_limits = collection.limits.owner_can_transfer - && Self::is_owner_or_admin_permissions(collection, sender); + && Self::is_owner_or_admin_permissions(collection, sender)?; let allowance_limit = if bypasses_limits { None - } else if let Some(amount) = Self::owned_amount(sender, collection, item_id) { + } else if let Some(amount) = Self::owned_amount(sender, collection, item_id)? { Some(amount) } else { fail!(Error::::NoPermission); @@ -1350,6 +1346,7 @@ Self::check_white_list(collection, spender)?; } + collection.consume_sload()?; let allowance: u128 = amount .checked_add(>::get( collection.id, @@ -1359,6 +1356,7 @@ if let Some(limit) = allowance_limit { ensure!(limit >= allowance, Error::::TokenValueTooLow); } + collection.consume_sstore()?; >::insert( collection.id, (item_id, sender.as_sub(), spender.as_sub()), @@ -1406,8 +1404,8 @@ return Self::transfer_internal(from, recipient, collection, item_id, amount); } - collection.consume_gas(2000000)?; // Check approval + collection.consume_sload()?; let approval: u128 = >::get(collection.id, (item_id, from.as_sub(), sender.as_sub())); @@ -1418,7 +1416,7 @@ ensure!( approval >= amount || (collection.limits.owner_can_transfer - && Self::is_owner_or_admin_permissions(collection, sender)), + && Self::is_owner_or_admin_permissions(collection, sender)?), Error::::NoPermission ); @@ -1429,6 +1427,7 @@ // Reduce approval by transferred amount or remove if remaining approval drops to 0 let allowance = approval.saturating_sub(amount); + collection.consume_sstore()?; if allowance > 0 { >::insert( collection.id, @@ -1476,14 +1475,14 @@ Self::token_exists(collection, item_id)?; ensure!( - ChainLimit::get().custom_data_limit >= data.len() as u32, + CUSTOM_DATA_LIMIT >= data.len() as u32, Error::::TokenVariableDataLimitExceeded ); // Modify permissions check ensure!( - Self::is_item_owner(sender, collection, item_id) - || Self::is_owner_or_admin_permissions(collection, sender), + Self::is_item_owner(sender, collection, item_id)? + || Self::is_owner_or_admin_permissions(collection, sender)?, Error::::NoPermission ); @@ -1524,9 +1523,9 @@ value: u128, ) -> DispatchResult { ensure!( - Self::is_item_owner(sender, collection, item_id) + Self::is_item_owner(sender, collection, item_id)? || (collection.limits.owner_can_transfer - && Self::is_owner_or_admin_permissions(collection, sender)), + && Self::is_owner_or_admin_permissions(collection, sender)?), Error::::NoPermission ); @@ -1568,6 +1567,7 @@ let collection_id = collection.id; // check token limit and account token limit + collection.consume_sload()?; let account_items: u32 = >::get(collection_id, recipient.as_sub()).len() as u32; ensure!( @@ -1606,7 +1606,7 @@ Error::::AccountTokenLimitExceeded ); - if !Self::is_owner_or_admin_permissions(collection, sender) { + if !Self::is_owner_or_admin_permissions(collection, sender)? { ensure!(collection.mint_mode, Error::::PublicMintingNotAllowed); Self::check_white_list(collection, owner)?; Self::check_white_list(collection, sender)?; @@ -1621,38 +1621,17 @@ ) -> DispatchResult { match target_collection.mode { CollectionMode::NFT => { - if let CreateItemData::NFT(data) = data { - // check sizes - ensure!( - ChainLimit::get().custom_data_limit >= data.const_data.len() as u32, - Error::::TokenConstDataLimitExceeded - ); - ensure!( - ChainLimit::get().custom_data_limit >= data.variable_data.len() as u32, - Error::::TokenVariableDataLimitExceeded - ); - } else { + if !matches!(data, CreateItemData::NFT(_)) { fail!(Error::::NotNftDataUsedToMintNftCollectionToken); } } CollectionMode::Fungible(_) => { - if let CreateItemData::Fungible(_) = data { - } else { + if !matches!(data, CreateItemData::Fungible(_)) { fail!(Error::::NotFungibleDataUsedToMintFungibleCollectionToken); } } CollectionMode::ReFungible => { if let CreateItemData::ReFungible(data) = data { - // check sizes - ensure!( - ChainLimit::get().custom_data_limit >= data.const_data.len() as u32, - Error::::TokenConstDataLimitExceeded - ); - ensure!( - ChainLimit::get().custom_data_limit >= data.variable_data.len() as u32, - Error::::TokenVariableDataLimitExceeded - ); - // Check refungibility limits ensure!( data.pieces <= MAX_REFUNGIBLE_PIECES, @@ -1680,8 +1659,8 @@ CreateItemData::NFT(data) => { let item = NftItemType { owner: owner.clone(), - const_data: data.const_data, - variable_data: data.variable_data, + const_data: data.const_data.into_inner(), + variable_data: data.variable_data.into_inner(), }; Self::add_nft_item(collection, item)?; @@ -1697,8 +1676,8 @@ let item = ReFungibleItemType { owner: owner_list, - const_data: data.const_data, - variable_data: data.variable_data, + const_data: data.const_data.into_inner(), + variable_data: data.variable_data.into_inner(), }; Self::add_refungible_item(collection, item)?; @@ -1716,20 +1695,29 @@ let collection_id = collection.id; // Does new owner already have an account? + collection.consume_sload()?; let balance: u128 = >::get(collection_id, owner.as_sub()).value; // Mint let item = FungibleItemType { value: balance.checked_add(value).ok_or(Error::::NumOverflow)?, }; + collection.consume_sstore()?; >::insert(collection_id, owner.as_sub(), item); // Update balance + collection.consume_sload()?; let new_balance = >::get(collection_id, owner.as_sub()) .checked_add(value) .ok_or(Error::::NumOverflow)?; + collection.consume_sstore()?; >::insert(collection_id, owner.as_sub(), new_balance); + collection.log(ERC20Events::Transfer { + from: H160::default(), + to: *owner.as_eth(), + value: value.into(), + })?; Self::deposit_event(RawEvent::ItemCreated(collection_id, 0, owner.clone())); Ok(()) } @@ -1751,7 +1739,7 @@ let value = item_owner.fraction; let owner = item_owner.owner.clone(); - Self::add_token_index(collection_id, current_index, &owner)?; + Self::add_token_index(collection, current_index, &owner)?; ::insert(collection_id, current_index); >::insert(collection_id, current_index, itemcopy); @@ -1777,7 +1765,7 @@ .ok_or(Error::::NumOverflow)?; let item_owner = item.owner.clone(); - Self::add_token_index(collection_id, current_index, &item.owner)?; + Self::add_token_index(collection, current_index, &item.owner)?; ::insert(collection_id, current_index); >::insert(collection_id, current_index, item); @@ -1815,7 +1803,7 @@ .iter() .find(|&i| i.owner == *owner) .ok_or(Error::::TokenNotFound)?; - Self::remove_token_index(collection_id, item_id, owner)?; + Self::remove_token_index(collection, item_id, owner)?; // update balance let new_balance = >::get(collection_id, rft_balance.owner.as_sub()) @@ -1848,7 +1836,7 @@ let item = >::get(collection_id, item_id).ok_or(Error::::TokenNotFound)?; - Self::remove_token_index(collection_id, item_id, &item.owner)?; + Self::remove_token_index(collection, item_id, &item.owner)?; // update balance let new_balance = >::get(collection_id, item.owner.as_sub()) @@ -1858,6 +1846,11 @@ >::remove(collection_id, item_id); >::remove(collection_id, item_id); + collection.log(ERC721Events::Transfer { + from: *item.owner.as_eth(), + to: H160::default(), + token_id: item_id.into(), + })?; Self::deposit_event(RawEvent::ItemDestroyed(collection.id, item_id)); Ok(()) } @@ -1914,9 +1907,10 @@ fn is_owner_or_admin_permissions( collection: &CollectionHandle, subject: &T::CrossAccountId, - ) -> bool { - *subject.as_sub() == collection.owner - || >::get(collection.id).contains(subject) + ) -> Result { + collection.consume_sload()?; + Ok(*subject.as_sub() == collection.owner + || >::get(collection.id).contains(subject)) } fn check_owner_or_admin_permissions( @@ -1924,7 +1918,7 @@ subject: &T::CrossAccountId, ) -> DispatchResult { ensure!( - Self::is_owner_or_admin_permissions(collection, subject), + Self::is_owner_or_admin_permissions(collection, subject)?, Error::::NoPermission ); @@ -1933,6 +1927,15 @@ fn owned_amount( subject: &T::CrossAccountId, + collection: &CollectionHandle, + item_id: TokenId, + ) -> Result, DispatchError> { + collection.consume_sload()?; + Ok(Self::owned_amount_unchecked(subject, collection, item_id)) + } + + fn owned_amount_unchecked( + subject: &T::CrossAccountId, target_collection: &CollectionHandle, item_id: TokenId, ) -> Option { @@ -1958,25 +1961,22 @@ subject: &T::CrossAccountId, target_collection: &CollectionHandle, item_id: TokenId, - ) -> bool { - match target_collection.mode { + ) -> Result { + Ok(match target_collection.mode { CollectionMode::Fungible(_) => true, - _ => Self::owned_amount(subject, target_collection, item_id).is_some(), - } + _ => Self::owned_amount(subject, target_collection, item_id)?.is_some(), + }) } fn check_white_list( collection: &CollectionHandle, address: &T::CrossAccountId, ) -> DispatchResult { - let collection_id = collection.id; - - let mes = Error::::AddresNotInWhiteList; + collection.consume_sload()?; ensure!( - >::contains_key(collection_id, address.as_sub()), - mes + >::contains_key(collection.id, address.as_sub()), + Error::::AddresNotInWhiteList, ); - Ok(()) } @@ -2005,22 +2005,39 @@ ) -> DispatchResult { let collection_id = collection.id; + collection.consume_sload()?; + collection.consume_sload()?; + let mut recipient_balance = >::get(collection_id, recipient.as_sub()); let mut balance = >::get(collection_id, owner.as_sub()); - ensure!(balance.value >= value, Error::::TokenValueTooLow); - // Send balance to recipient (updates balanceOf of recipient) - Self::add_fungible_item(collection, recipient, value)?; + recipient_balance.value = recipient_balance + .value + .checked_add(value) + .ok_or(Error::::NumOverflow)?; + balance.value = balance + .value + .checked_sub(value) + .ok_or(Error::::TokenValueTooLow)?; - // update balanceOf of sender - >::insert(collection_id, owner.as_sub(), balance.value - value); + // update balanceOf + collection.consume_sstore()?; + collection.consume_sstore()?; + if balance.value != 0 { + >::insert(collection_id, owner.as_sub(), balance.value); + } else { + >::remove(collection_id, owner.as_sub()); + } + >::insert(collection_id, recipient.as_sub(), recipient_balance.value); // Reduce or remove sender - if balance.value == value { + collection.consume_sstore()?; + collection.consume_sstore()?; + if balance.value != 0 { + >::insert(collection_id, owner.as_sub(), balance); + } else { >::remove(collection_id, owner.as_sub()); - } else { - balance.value -= value; - >::insert(collection_id, owner.as_sub(), balance); } + >::insert(collection_id, recipient.as_sub(), recipient_balance); collection.log(ERC20Events::Transfer { from: *owner.as_eth(), @@ -2046,6 +2063,7 @@ new_owner: T::CrossAccountId, ) -> DispatchResult { let collection_id = collection.id; + collection.consume_sload()?; let full_item = >::get(collection_id, item_id) .ok_or(Error::::TokenNotFound)?; @@ -2058,15 +2076,19 @@ ensure!(amount >= value, Error::::TokenValueTooLow); + collection.consume_sload()?; // update balance let balance_old_owner = >::get(collection_id, item.owner.as_sub()) .checked_sub(value) .ok_or(Error::::NumOverflow)?; + collection.consume_sstore()?; >::insert(collection_id, item.owner.as_sub(), balance_old_owner); + collection.consume_sload()?; let balance_new_owner = >::get(collection_id, new_owner.as_sub()) .checked_add(value) .ok_or(Error::::NumOverflow)?; + collection.consume_sstore()?; >::insert(collection_id, new_owner.as_sub(), balance_new_owner); let old_owner = item.owner.clone(); @@ -2083,10 +2105,11 @@ .find(|i| i.owner == owner) .expect("old owner does present in refungible") .owner = new_owner.clone(); + collection.consume_sstore()?; >::insert(collection_id, item_id, new_full_item); // update index collection - Self::move_token_index(collection_id, item_id, &old_owner, &new_owner)?; + Self::move_token_index(collection, item_id, &old_owner, &new_owner)?; } else { new_full_item .owner @@ -2110,9 +2133,10 @@ owner: new_owner.clone(), fraction: value, }); - Self::add_token_index(collection_id, item_id, &new_owner)?; + Self::add_token_index(collection, item_id, &new_owner)?; } + collection.consume_sstore()?; >::insert(collection_id, item_id, new_full_item); } @@ -2134,29 +2158,35 @@ new_owner: T::CrossAccountId, ) -> DispatchResult { let collection_id = collection.id; + collection.consume_sload()?; let mut item = >::get(collection_id, item_id).ok_or(Error::::TokenNotFound)?; ensure!(sender == item.owner, Error::::MustBeTokenOwner); + collection.consume_sload()?; // update balance let balance_old_owner = >::get(collection_id, item.owner.as_sub()) .checked_sub(1) .ok_or(Error::::NumOverflow)?; + collection.consume_sstore()?; >::insert(collection_id, item.owner.as_sub(), balance_old_owner); + collection.consume_sload()?; let balance_new_owner = >::get(collection_id, new_owner.as_sub()) .checked_add(1) .ok_or(Error::::NumOverflow)?; + collection.consume_sstore()?; >::insert(collection_id, new_owner.as_sub(), balance_new_owner); // change owner let old_owner = item.owner.clone(); item.owner = new_owner.clone(); + collection.consume_sstore()?; >::insert(collection_id, item_id, item); // update index collection - Self::move_token_index(collection_id, item_id, &old_owner, &new_owner)?; + Self::move_token_index(collection, item_id, &old_owner, &new_owner)?; collection.log(ERC721Events::Transfer { from: *sender.as_eth(), @@ -2236,7 +2266,12 @@ fn init_nft_token(collection_id: CollectionId, item: &NftItemType) { let current_index = ::get(collection_id).checked_add(1).unwrap(); - Self::add_token_index(collection_id, current_index, &item.owner).unwrap(); + Self::add_token_index( + &CollectionHandle::get(collection_id).unwrap(), + current_index, + &item.owner, + ) + .unwrap(); ::insert(collection_id, current_index); @@ -2255,7 +2290,12 @@ ) { let current_index = ::get(collection_id).checked_add(1).unwrap(); - Self::add_token_index(collection_id, current_index, owner).unwrap(); + Self::add_token_index( + &CollectionHandle::get(collection_id).unwrap(), + current_index, + owner, + ) + .unwrap(); ::insert(collection_id, current_index); @@ -2276,7 +2316,12 @@ let value = item.owner.first().unwrap().fraction; let owner = item.owner.first().unwrap().owner.clone(); - Self::add_token_index(collection_id, current_index, &owner).unwrap(); + Self::add_token_index( + &CollectionHandle::get(collection_id).unwrap(), + current_index, + &owner, + ) + .unwrap(); ::insert(collection_id, current_index); @@ -2288,51 +2333,61 @@ } fn add_token_index( - collection_id: CollectionId, + collection: &CollectionHandle, item_index: TokenId, owner: &T::CrossAccountId, ) -> DispatchResult { // add to account limit + collection.consume_sload()?; if >::contains_key(owner.as_sub()) { // bound Owned tokens by a single address + collection.consume_sload()?; let count = >::get(owner.as_sub()); ensure!( - count < ChainLimit::get().account_token_ownership_limit, + count < ACCOUNT_TOKEN_OWNERSHIP_LIMIT, Error::::AddressOwnershipLimitExceeded ); + collection.consume_sstore()?; >::insert( owner.as_sub(), count.checked_add(1).ok_or(Error::::NumOverflow)?, ); } else { + collection.consume_sstore()?; >::insert(owner.as_sub(), 1); } - let list_exists = >::contains_key(collection_id, owner.as_sub()); + collection.consume_sload()?; + let list_exists = >::contains_key(collection.id, owner.as_sub()); if list_exists { - let mut list = >::get(collection_id, owner.as_sub()); + collection.consume_sload()?; + let mut list = >::get(collection.id, owner.as_sub()); let item_contains = list.contains(&item_index.clone()); if !item_contains { list.push(item_index); } - >::insert(collection_id, owner.as_sub(), list); + collection.consume_sstore()?; + >::insert(collection.id, owner.as_sub(), list); } else { let itm = vec![item_index]; - >::insert(collection_id, owner.as_sub(), itm); + collection.consume_sstore()?; + >::insert(collection.id, owner.as_sub(), itm); } Ok(()) } fn remove_token_index( - collection_id: CollectionId, + collection: &CollectionHandle, item_index: TokenId, owner: &T::CrossAccountId, ) -> DispatchResult { // update counter + collection.consume_sload()?; + collection.consume_sstore()?; >::insert( owner.as_sub(), >::get(owner.as_sub()) @@ -2340,14 +2395,17 @@ .ok_or(Error::::NumOverflow)?, ); - let list_exists = >::contains_key(collection_id, owner.as_sub()); + collection.consume_sload()?; + let list_exists = >::contains_key(collection.id, owner.as_sub()); if list_exists { - let mut list = >::get(collection_id, owner.as_sub()); + collection.consume_sload()?; + let mut list = >::get(collection.id, owner.as_sub()); let item_contains = list.contains(&item_index.clone()); if item_contains { list.retain(|&item| item != item_index); - >::insert(collection_id, owner.as_sub(), list); + collection.consume_sstore()?; + >::insert(collection.id, owner.as_sub(), list); } } @@ -2355,13 +2413,13 @@ } fn move_token_index( - collection_id: CollectionId, + collection: &CollectionHandle, item_index: TokenId, old_owner: &T::CrossAccountId, new_owner: &T::CrossAccountId, ) -> DispatchResult { - Self::remove_token_index(collection_id, item_index, old_owner)?; - Self::add_token_index(collection_id, item_index, new_owner)?; + Self::remove_token_index(collection, item_index, old_owner)?; + Self::add_token_index(collection, item_index, new_owner)?; Ok(()) } --- a/pallets/nft/src/sponsorship.rs +++ b/pallets/nft/src/sponsorship.rs @@ -1,15 +1,18 @@ use crate::{ Config, Call, CollectionById, CreateItemBasket, VariableMetaDataBasket, - ReFungibleTransferBasket, FungibleTransferBasket, NftTransferBasket, ChainLimit, - CreateItemData, CollectionMode, + ReFungibleTransferBasket, FungibleTransferBasket, NftTransferBasket, CreateItemData, + CollectionMode, }; use core::marker::PhantomData; use up_sponsorship::SponsorshipHandler; use frame_support::{ - traits::IsSubType, - storage::{StorageMap, StorageDoubleMap, StorageValue}, + traits::{IsSubType}, + storage::{StorageMap, StorageDoubleMap}, +}; +use nft_data_structs::{ + TokenId, CollectionId, NFT_SPONSOR_TRANSFER_TIMEOUT, REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT, + FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT, }; -use nft_data_structs::{TokenId, CollectionId}; pub struct NftSponsorshipHandler(PhantomData); impl NftSponsorshipHandler { @@ -47,7 +50,6 @@ item_id: &TokenId, ) -> Option { let collection = CollectionById::::get(collection_id)?; - let limits = ChainLimit::get(); let mut sponsor_transfer = false; if collection.sponsorship.confirmed() { @@ -62,7 +64,7 @@ let limit: u32 = if collection_limits.sponsor_transfer_timeout > 0 { collection_limits.sponsor_transfer_timeout } else { - limits.nft_sponsor_transfer_timeout + NFT_SPONSOR_TRANSFER_TIMEOUT }; let mut sponsored = true; @@ -84,7 +86,7 @@ let limit: u32 = if collection_limits.sponsor_transfer_timeout > 0 { collection_limits.sponsor_transfer_timeout } else { - limits.fungible_sponsor_transfer_timeout + FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT }; let block_number = >::block_number() as T::BlockNumber; @@ -107,7 +109,7 @@ let limit: u32 = if collection_limits.sponsor_transfer_timeout > 0 { collection_limits.sponsor_transfer_timeout } else { - limits.refungible_sponsor_transfer_timeout + REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT }; let mut sponsored = true; --- a/pallets/nft/src/tests.rs +++ b/pallets/nft/src/tests.rs @@ -1,40 +1,18 @@ // Tests to be written here use super::*; use crate::mock::*; -use crate::{AccessMode, CollectionMode, Ownership, ChainLimits, CreateItemData}; +use crate::{AccessMode, CollectionMode, Ownership, CreateItemData}; use nft_data_structs::{ CreateNftData, CreateFungibleData, CreateReFungibleData, CollectionId, TokenId, MAX_DECIMAL_POINTS, }; use frame_support::{assert_noop, assert_ok}; -use frame_system::{RawOrigin}; - -fn default_collection_numbers_limit() -> u32 { - 10 -} - -fn default_limits() { - assert_ok!(TemplateModule::set_chain_limits( - RawOrigin::Root.into(), - ChainLimits { - collection_numbers_limit: default_collection_numbers_limit(), - account_token_ownership_limit: 10, - collections_admins_limit: 5, - custom_data_limit: 2048, - nft_sponsor_transfer_timeout: 15, - fungible_sponsor_transfer_timeout: 15, - refungible_sponsor_transfer_timeout: 15, - const_on_chain_schema_limit: 1024, - offchain_schema_limit: 1024, - variable_on_chain_schema_limit: 1024, - } - )); -} +use sp_std::convert::TryInto; fn default_nft_data() -> CreateNftData { CreateNftData { - const_data: vec![1, 2, 3], - variable_data: vec![3, 2, 1], + const_data: vec![1, 2, 3].try_into().unwrap(), + variable_data: vec![3, 2, 1].try_into().unwrap(), } } @@ -44,8 +22,8 @@ fn default_re_fungible_data() -> CreateReFungibleData { CreateReFungibleData { - const_data: vec![1, 2, 3], - variable_data: vec![3, 2, 1], + const_data: vec![1, 2, 3].try_into().unwrap(), + variable_data: vec![3, 2, 1].try_into().unwrap(), pieces: 1023, } } @@ -112,7 +90,6 @@ #[test] fn set_version_schema() { new_test_ext().execute_with(|| { - default_limits(); let origin1 = Origin::signed(1); let collection_id = create_test_collection(&CollectionMode::NFT, 1); @@ -133,8 +110,6 @@ #[test] fn create_fungible_collection_fails_with_large_decimal_numbers() { new_test_ext().execute_with(|| { - default_limits(); - let col_name1: Vec = "Test1\0".encode_utf16().collect::>(); let col_desc1: Vec = "TestDescription1\0".encode_utf16().collect::>(); let token_prefix1: Vec = b"token_prefix1\0".to_vec(); @@ -156,14 +131,13 @@ #[test] fn create_nft_item() { new_test_ext().execute_with(|| { - default_limits(); let collection_id = create_test_collection(&CollectionMode::NFT, 1); let data = default_nft_data(); create_test_item(collection_id, &data.clone().into()); let item = TemplateModule::nft_item_id(collection_id, 1).unwrap(); - assert_eq!(item.const_data, data.const_data); - assert_eq!(item.variable_data, data.variable_data); + assert_eq!(item.const_data, data.const_data.into_inner()); + assert_eq!(item.variable_data, data.variable_data.into_inner()); }); } @@ -172,8 +146,6 @@ #[test] fn create_nft_multiple_items() { new_test_ext().execute_with(|| { - default_limits(); - create_test_collection(&CollectionMode::NFT, 1); let origin1 = Origin::signed(1); @@ -190,10 +162,10 @@ .map(|d| { d.into() }) .collect() )); - for (index, data) in items_data.iter().enumerate() { + for (index, data) in items_data.into_iter().enumerate() { let item = TemplateModule::nft_item_id(1, (index + 1) as TokenId).unwrap(); - assert_eq!(item.const_data.to_vec(), data.const_data); - assert_eq!(item.variable_data.to_vec(), data.variable_data); + assert_eq!(item.const_data.to_vec(), data.const_data.into_inner()); + assert_eq!(item.variable_data.to_vec(), data.variable_data.into_inner()); } }); } @@ -201,14 +173,13 @@ #[test] fn create_refungible_item() { new_test_ext().execute_with(|| { - default_limits(); let collection_id = create_test_collection(&CollectionMode::ReFungible, 1); let data = default_re_fungible_data(); create_test_item(collection_id, &data.clone().into()); let item = TemplateModule::refungible_item_id(collection_id, 1).unwrap(); - assert_eq!(item.const_data, data.const_data); - assert_eq!(item.variable_data, data.variable_data); + assert_eq!(item.const_data, data.const_data.into_inner()); + assert_eq!(item.variable_data, data.variable_data.into_inner()); assert_eq!( item.owner[0], Ownership { @@ -222,8 +193,6 @@ #[test] fn create_multiple_refungible_items() { new_test_ext().execute_with(|| { - default_limits(); - create_test_collection(&CollectionMode::ReFungible, 1); let origin1 = Origin::signed(1); @@ -244,10 +213,10 @@ .map(|d| { d.into() }) .collect() )); - for (index, data) in items_data.iter().enumerate() { + for (index, data) in items_data.into_iter().enumerate() { let item = TemplateModule::refungible_item_id(1, (index + 1) as TokenId).unwrap(); - assert_eq!(item.const_data.to_vec(), data.const_data); - assert_eq!(item.variable_data.to_vec(), data.variable_data); + assert_eq!(item.const_data.to_vec(), data.const_data.into_inner()); + assert_eq!(item.variable_data.to_vec(), data.variable_data.into_inner()); assert_eq!( item.owner[0], Ownership { @@ -262,8 +231,6 @@ #[test] fn create_fungible_item() { new_test_ext().execute_with(|| { - default_limits(); - let collection_id = create_test_collection(&CollectionMode::Fungible(3), 1); let data = default_fungible_data(); @@ -302,8 +269,6 @@ #[test] fn transfer_fungible_item() { new_test_ext().execute_with(|| { - default_limits(); - let collection_id = create_test_collection(&CollectionMode::Fungible(3), 1); let origin1 = Origin::signed(1); @@ -344,8 +309,6 @@ #[test] fn transfer_refungible_item() { new_test_ext().execute_with(|| { - default_limits(); - let collection_id = create_test_collection(&CollectionMode::ReFungible, 1); let data = default_re_fungible_data(); @@ -355,8 +318,8 @@ let origin2 = Origin::signed(2); { let item = TemplateModule::refungible_item_id(collection_id, 1).unwrap(); - assert_eq!(item.const_data, data.const_data); - assert_eq!(item.variable_data, data.variable_data); + assert_eq!(item.const_data, data.const_data.into_inner()); + assert_eq!(item.variable_data, data.variable_data.into_inner()); assert_eq!( item.owner[0], Ownership { @@ -441,8 +404,6 @@ #[test] fn transfer_nft_item() { new_test_ext().execute_with(|| { - default_limits(); - let collection_id = create_test_collection(&CollectionMode::NFT, 1); let data = default_nft_data(); @@ -464,8 +425,6 @@ #[test] fn nft_approve_and_transfer_from() { new_test_ext().execute_with(|| { - default_limits(); - let collection_id = create_test_collection(&CollectionMode::NFT, 1); let data = default_nft_data(); @@ -503,8 +462,6 @@ #[test] fn nft_approve_and_transfer_from_white_list() { new_test_ext().execute_with(|| { - default_limits(); - let collection_id = create_test_collection(&CollectionMode::NFT, 1); let origin1 = Origin::signed(1); @@ -514,8 +471,8 @@ create_test_item(collection_id, &data.clone().into()); assert_eq!( - TemplateModule::nft_item_id(1, 1).unwrap().const_data, - data.const_data + &TemplateModule::nft_item_id(1, 1).unwrap().const_data, + &data.const_data.into_inner() ); assert_eq!(TemplateModule::balance_count(1, 1), 1); assert_eq!(TemplateModule::address_tokens(1, 1), [1]); @@ -573,8 +530,6 @@ #[test] fn refungible_approve_and_transfer_from() { new_test_ext().execute_with(|| { - default_limits(); - let collection_id = create_test_collection(&CollectionMode::ReFungible, 1); let origin1 = Origin::signed(1); @@ -636,8 +591,6 @@ #[test] fn fungible_approve_and_transfer_from() { new_test_ext().execute_with(|| { - default_limits(); - let collection_id = create_test_collection(&CollectionMode::Fungible(3), 1); let data = default_fungible_data(); @@ -710,8 +663,6 @@ #[test] fn change_collection_owner() { new_test_ext().execute_with(|| { - default_limits(); - let collection_id = create_test_collection(&CollectionMode::NFT, 1); let origin1 = Origin::signed(1); @@ -730,8 +681,6 @@ #[test] fn destroy_collection() { new_test_ext().execute_with(|| { - default_limits(); - let collection_id = create_test_collection(&CollectionMode::NFT, 1); let origin1 = Origin::signed(1); @@ -742,8 +691,6 @@ #[test] fn burn_nft_item() { new_test_ext().execute_with(|| { - default_limits(); - let collection_id = create_test_collection(&CollectionMode::NFT, 1); let origin1 = Origin::signed(1); @@ -773,8 +720,6 @@ #[test] fn burn_fungible_item() { new_test_ext().execute_with(|| { - default_limits(); - let collection_id = create_test_collection(&CollectionMode::Fungible(3), 1); let origin1 = Origin::signed(1); @@ -804,8 +749,6 @@ #[test] fn burn_refungible_item() { new_test_ext().execute_with(|| { - default_limits(); - let collection_id = create_test_collection(&CollectionMode::ReFungible, 1); let origin1 = Origin::signed(1); @@ -851,8 +794,6 @@ #[test] fn add_collection_admin() { new_test_ext().execute_with(|| { - default_limits(); - let collection1_id = create_test_collection_for_owner(&CollectionMode::NFT, 1, 1); create_test_collection_for_owner(&CollectionMode::NFT, 2, 2); create_test_collection_for_owner(&CollectionMode::NFT, 3, 3); @@ -879,8 +820,6 @@ #[test] fn remove_collection_admin() { new_test_ext().execute_with(|| { - default_limits(); - let collection1_id = create_test_collection_for_owner(&CollectionMode::NFT, 1, 1); create_test_collection_for_owner(&CollectionMode::NFT, 2, 2); create_test_collection_for_owner(&CollectionMode::NFT, 3, 3); @@ -916,8 +855,6 @@ #[test] fn balance_of() { new_test_ext().execute_with(|| { - default_limits(); - let nft_collection_id = create_test_collection(&CollectionMode::NFT, 1); let fungible_collection_id = create_test_collection(&CollectionMode::Fungible(3), 2); let re_fungible_collection_id = create_test_collection(&CollectionMode::ReFungible, 3); @@ -969,8 +906,6 @@ #[test] fn approve() { new_test_ext().execute_with(|| { - default_limits(); - let collection_id = create_test_collection(&CollectionMode::NFT, 1); let data = default_nft_data(); @@ -987,8 +922,6 @@ #[test] fn transfer_from() { new_test_ext().execute_with(|| { - default_limits(); - let collection_id = create_test_collection(&CollectionMode::NFT, 1); let origin1 = Origin::signed(1); let origin2 = Origin::signed(2); @@ -1051,8 +984,6 @@ #[test] fn owner_can_add_address_to_white_list() { new_test_ext().execute_with(|| { - default_limits(); - let collection_id = create_test_collection(&CollectionMode::NFT, 1); let origin1 = Origin::signed(1); @@ -1068,8 +999,6 @@ #[test] fn admin_can_add_address_to_white_list() { new_test_ext().execute_with(|| { - default_limits(); - let collection_id = create_test_collection(&CollectionMode::NFT, 1); let origin1 = Origin::signed(1); let origin2 = Origin::signed(2); @@ -1091,8 +1020,6 @@ #[test] fn nonprivileged_user_cannot_add_address_to_white_list() { new_test_ext().execute_with(|| { - default_limits(); - let collection_id = create_test_collection(&CollectionMode::NFT, 1); let origin2 = Origin::signed(2); @@ -1106,8 +1033,6 @@ #[test] fn nobody_can_add_address_to_white_list_of_nonexisting_collection() { new_test_ext().execute_with(|| { - default_limits(); - let origin1 = Origin::signed(1); assert_noop!( @@ -1120,8 +1045,6 @@ #[test] fn nobody_can_add_address_to_white_list_of_deleted_collection() { new_test_ext().execute_with(|| { - default_limits(); - let collection_id = create_test_collection(&CollectionMode::NFT, 1); let origin1 = Origin::signed(1); @@ -1140,8 +1063,6 @@ #[test] fn address_is_already_added_to_white_list() { new_test_ext().execute_with(|| { - default_limits(); - let collection_id = create_test_collection(&CollectionMode::NFT, 1); let origin1 = Origin::signed(1); @@ -1162,8 +1083,6 @@ #[test] fn owner_can_remove_address_from_white_list() { new_test_ext().execute_with(|| { - default_limits(); - let collection_id = create_test_collection(&CollectionMode::NFT, 1); let origin1 = Origin::signed(1); @@ -1184,8 +1103,6 @@ #[test] fn admin_can_remove_address_from_white_list() { new_test_ext().execute_with(|| { - default_limits(); - let collection_id = create_test_collection(&CollectionMode::NFT, 1); let origin1 = Origin::signed(1); let origin2 = Origin::signed(2); @@ -1213,8 +1130,6 @@ #[test] fn nonprivileged_user_cannot_remove_address_from_white_list() { new_test_ext().execute_with(|| { - default_limits(); - let collection_id = create_test_collection(&CollectionMode::NFT, 1); let origin1 = Origin::signed(1); let origin2 = Origin::signed(2); @@ -1235,7 +1150,6 @@ #[test] fn nobody_can_remove_address_from_white_list_of_nonexisting_collection() { new_test_ext().execute_with(|| { - default_limits(); let origin1 = Origin::signed(1); assert_noop!( @@ -1248,8 +1162,6 @@ #[test] fn nobody_can_remove_address_from_white_list_of_deleted_collection() { new_test_ext().execute_with(|| { - default_limits(); - let collection_id = create_test_collection(&CollectionMode::NFT, 1); let origin1 = Origin::signed(1); let origin2 = Origin::signed(2); @@ -1272,8 +1184,6 @@ #[test] fn address_is_already_removed_from_white_list() { new_test_ext().execute_with(|| { - default_limits(); - let collection_id = create_test_collection(&CollectionMode::NFT, 1); let origin1 = Origin::signed(1); @@ -1300,8 +1210,6 @@ #[test] fn white_list_test_1() { new_test_ext().execute_with(|| { - default_limits(); - let collection_id = create_test_collection(&CollectionMode::NFT, 1); let origin1 = Origin::signed(1); @@ -1330,8 +1238,6 @@ #[test] fn white_list_test_2() { new_test_ext().execute_with(|| { - default_limits(); - let collection_id = create_test_collection(&CollectionMode::NFT, 1); let origin1 = Origin::signed(1); @@ -1381,8 +1287,6 @@ #[test] fn white_list_test_3() { new_test_ext().execute_with(|| { - default_limits(); - let collection_id = create_test_collection(&CollectionMode::NFT, 1); let origin1 = Origin::signed(1); @@ -1411,8 +1315,6 @@ #[test] fn white_list_test_4() { new_test_ext().execute_with(|| { - default_limits(); - let collection_id = create_test_collection(&CollectionMode::NFT, 1); let origin1 = Origin::signed(1); @@ -1463,8 +1365,6 @@ #[test] fn white_list_test_5() { new_test_ext().execute_with(|| { - default_limits(); - let collection_id = create_test_collection(&CollectionMode::NFT, 1); let origin1 = Origin::signed(1); @@ -1488,8 +1388,6 @@ #[test] fn white_list_test_6() { new_test_ext().execute_with(|| { - default_limits(); - let collection_id = create_test_collection(&CollectionMode::NFT, 1); let origin1 = Origin::signed(1); @@ -1516,8 +1414,6 @@ #[test] fn white_list_test_7() { new_test_ext().execute_with(|| { - default_limits(); - let collection_id = create_test_collection(&CollectionMode::NFT, 1); let data = default_nft_data(); @@ -1548,8 +1444,6 @@ #[test] fn white_list_test_8() { new_test_ext().execute_with(|| { - default_limits(); - let collection_id = create_test_collection(&CollectionMode::NFT, 1); let data = default_nft_data(); @@ -1598,8 +1492,6 @@ #[test] fn white_list_test_9() { new_test_ext().execute_with(|| { - default_limits(); - let collection_id = create_test_collection(&CollectionMode::NFT, 1); let origin1 = Origin::signed(1); @@ -1623,8 +1515,6 @@ #[test] fn white_list_test_10() { new_test_ext().execute_with(|| { - default_limits(); - let collection_id = create_test_collection(&CollectionMode::NFT, 1); let origin1 = Origin::signed(1); @@ -1660,8 +1550,6 @@ #[test] fn white_list_test_11() { new_test_ext().execute_with(|| { - default_limits(); - let collection_id = create_test_collection(&CollectionMode::NFT, 1); let origin1 = Origin::signed(1); @@ -1694,8 +1582,6 @@ #[test] fn white_list_test_12() { new_test_ext().execute_with(|| { - default_limits(); - let collection_id = create_test_collection(&CollectionMode::NFT, 1); let origin1 = Origin::signed(1); @@ -1723,8 +1609,6 @@ #[test] fn white_list_test_13() { new_test_ext().execute_with(|| { - default_limits(); - let collection_id = create_test_collection(&CollectionMode::NFT, 1); let origin1 = Origin::signed(1); @@ -1749,8 +1633,6 @@ #[test] fn white_list_test_14() { new_test_ext().execute_with(|| { - default_limits(); - let collection_id = create_test_collection(&CollectionMode::NFT, 1); let origin1 = Origin::signed(1); @@ -1786,8 +1668,6 @@ #[test] fn white_list_test_15() { new_test_ext().execute_with(|| { - default_limits(); - let collection_id = create_test_collection(&CollectionMode::NFT, 1); let origin1 = Origin::signed(1); @@ -1815,8 +1695,6 @@ #[test] fn white_list_test_16() { new_test_ext().execute_with(|| { - default_limits(); - let collection_id = create_test_collection(&CollectionMode::NFT, 1); let origin1 = Origin::signed(1); @@ -1851,8 +1729,6 @@ #[test] fn total_number_collections_bound() { new_test_ext().execute_with(|| { - default_limits(); - create_test_collection(&CollectionMode::NFT, 1); }); } @@ -1861,11 +1737,9 @@ #[test] fn total_number_collections_bound_neg() { new_test_ext().execute_with(|| { - default_limits(); - let origin1 = Origin::signed(1); - for i in 0..default_collection_numbers_limit() { + for i in 0..COLLECTION_NUMBER_LIMIT { create_test_collection(&CollectionMode::NFT, i + 1); } @@ -1891,8 +1765,6 @@ #[test] fn owned_tokens_bound() { new_test_ext().execute_with(|| { - default_limits(); - let collection_id = create_test_collection(&CollectionMode::NFT, 1); let data = default_nft_data(); @@ -1905,28 +1777,16 @@ #[test] fn owned_tokens_bound_neg() { new_test_ext().execute_with(|| { - assert_ok!(TemplateModule::set_chain_limits( - RawOrigin::Root.into(), - ChainLimits { - collection_numbers_limit: 10, - account_token_ownership_limit: 1, - collections_admins_limit: 5, - custom_data_limit: 2048, - nft_sponsor_transfer_timeout: 15, - fungible_sponsor_transfer_timeout: 15, - refungible_sponsor_transfer_timeout: 15, - const_on_chain_schema_limit: 1024, - offchain_schema_limit: 1024, - variable_on_chain_schema_limit: 1024, - } - )); - let collection_id = create_test_collection(&CollectionMode::NFT, 1); let origin1 = Origin::signed(1); + + for _ in 0..ACCOUNT_TOKEN_OWNERSHIP_LIMIT { + let data = default_nft_data(); + create_test_item(collection_id, &data.clone().into()); + } + let data = default_nft_data(); - create_test_item(collection_id, &data.clone().into()); - assert_noop!( TemplateModule::create_item(origin1, 1, account(1), data.into()), Error::::AddressOwnershipLimitExceeded @@ -1938,22 +1798,6 @@ #[test] fn collection_admins_bound() { new_test_ext().execute_with(|| { - assert_ok!(TemplateModule::set_chain_limits( - RawOrigin::Root.into(), - ChainLimits { - collection_numbers_limit: 10, - account_token_ownership_limit: 10, - collections_admins_limit: 2, - custom_data_limit: 2048, - nft_sponsor_transfer_timeout: 15, - fungible_sponsor_transfer_timeout: 15, - refungible_sponsor_transfer_timeout: 15, - const_on_chain_schema_limit: 1024, - offchain_schema_limit: 1024, - variable_on_chain_schema_limit: 1024, - } - )); - let collection_id = create_test_collection(&CollectionMode::NFT, 1); let origin1 = Origin::signed(1); @@ -1975,184 +1819,32 @@ #[test] fn collection_admins_bound_neg() { new_test_ext().execute_with(|| { - assert_ok!(TemplateModule::set_chain_limits( - RawOrigin::Root.into(), - ChainLimits { - collection_numbers_limit: 10, - account_token_ownership_limit: 1, - collections_admins_limit: 1, - custom_data_limit: 2048, - nft_sponsor_transfer_timeout: 15, - fungible_sponsor_transfer_timeout: 15, - refungible_sponsor_transfer_timeout: 15, - const_on_chain_schema_limit: 1024, - offchain_schema_limit: 1024, - variable_on_chain_schema_limit: 1024, - } - )); - let collection_id = create_test_collection(&CollectionMode::NFT, 1); let origin1 = Origin::signed(1); - assert_ok!(TemplateModule::add_collection_admin( - origin1.clone(), - collection_id, - account(2) - )); + for i in 0..COLLECTION_ADMINS_LIMIT { + assert_ok!(TemplateModule::add_collection_admin( + origin1.clone(), + collection_id, + account(2 + i) + )); + } assert_noop!( - TemplateModule::add_collection_admin(origin1, collection_id, account(3)), + TemplateModule::add_collection_admin( + origin1, + collection_id, + account(3 + COLLECTION_ADMINS_LIMIT) + ), Error::::CollectionAdminsLimitExceeded - ); - }); -} - -// NFT custom data size. Negative test const_data. -#[test] -fn custom_data_size_nft_const_data_bound_neg() { - new_test_ext().execute_with(|| { - assert_ok!(TemplateModule::set_chain_limits( - RawOrigin::Root.into(), - ChainLimits { - collection_numbers_limit: 10, - account_token_ownership_limit: 10, - collections_admins_limit: 5, - custom_data_limit: 2, - nft_sponsor_transfer_timeout: 15, - fungible_sponsor_transfer_timeout: 15, - refungible_sponsor_transfer_timeout: 15, - const_on_chain_schema_limit: 1024, - offchain_schema_limit: 1024, - variable_on_chain_schema_limit: 1024, - } - )); - - let collection_id = create_test_collection(&CollectionMode::NFT, 1); - - let origin1 = Origin::signed(1); - let too_big_const_data = CreateItemData::NFT(CreateNftData { - const_data: vec![1, 2, 3, 4], - variable_data: vec![], - }); - - assert_noop!( - TemplateModule::create_item(origin1, collection_id, account(1), too_big_const_data), - Error::::TokenConstDataLimitExceeded - ); - }); -} - -// NFT custom data size. Negative test variable_data. -#[test] -fn custom_data_size_nft_variable_data_bound_neg() { - new_test_ext().execute_with(|| { - assert_ok!(TemplateModule::set_chain_limits( - RawOrigin::Root.into(), - ChainLimits { - collection_numbers_limit: 10, - account_token_ownership_limit: 10, - collections_admins_limit: 5, - custom_data_limit: 2, - nft_sponsor_transfer_timeout: 15, - fungible_sponsor_transfer_timeout: 15, - refungible_sponsor_transfer_timeout: 15, - const_on_chain_schema_limit: 1024, - offchain_schema_limit: 1024, - variable_on_chain_schema_limit: 1024, - } - )); - - let collection_id = create_test_collection(&CollectionMode::NFT, 1); - - let origin1 = Origin::signed(1); - let too_big_const_data = CreateItemData::NFT(CreateNftData { - const_data: vec![], - variable_data: vec![1, 2, 3, 4], - }); - - assert_noop!( - TemplateModule::create_item(origin1, collection_id, account(1), too_big_const_data), - Error::::TokenVariableDataLimitExceeded - ); - }); -} - -// Re fungible custom data size. Negative test const_data. -#[test] -fn custom_data_size_re_fungible_const_data_bound_neg() { - new_test_ext().execute_with(|| { - assert_ok!(TemplateModule::set_chain_limits( - RawOrigin::Root.into(), - ChainLimits { - collection_numbers_limit: 10, - account_token_ownership_limit: 10, - collections_admins_limit: 5, - custom_data_limit: 2, - nft_sponsor_transfer_timeout: 15, - fungible_sponsor_transfer_timeout: 15, - refungible_sponsor_transfer_timeout: 15, - const_on_chain_schema_limit: 1024, - offchain_schema_limit: 1024, - variable_on_chain_schema_limit: 1024, - } - )); - - let collection_id = create_test_collection(&CollectionMode::NFT, 1); - - let origin1 = Origin::signed(1); - let too_big_const_data = CreateItemData::NFT(CreateNftData { - const_data: vec![1, 2, 3, 4], - variable_data: vec![], - }); - - assert_noop!( - TemplateModule::create_item(origin1, collection_id, account(1), too_big_const_data), - Error::::TokenConstDataLimitExceeded ); }); } - -// Re fungible custom data size. Negative test variable_data. -#[test] -fn custom_data_size_re_fungible_variable_data_bound_neg() { - new_test_ext().execute_with(|| { - assert_ok!(TemplateModule::set_chain_limits( - RawOrigin::Root.into(), - ChainLimits { - collection_numbers_limit: 10, - account_token_ownership_limit: 10, - collections_admins_limit: 5, - custom_data_limit: 2, - nft_sponsor_transfer_timeout: 15, - fungible_sponsor_transfer_timeout: 15, - refungible_sponsor_transfer_timeout: 15, - const_on_chain_schema_limit: 1024, - offchain_schema_limit: 1024, - variable_on_chain_schema_limit: 1024, - } - )); - - let collection_id = create_test_collection(&CollectionMode::NFT, 1); - - let origin1 = Origin::signed(1); - let too_big_const_data = CreateItemData::NFT(CreateNftData { - const_data: vec![], - variable_data: vec![1, 2, 3, 4], - }); - - assert_noop!( - TemplateModule::create_item(origin1, collection_id, account(1), too_big_const_data), - Error::::TokenVariableDataLimitExceeded - ); - }); -} // #endregion #[test] fn set_const_on_chain_schema() { new_test_ext().execute_with(|| { - default_limits(); - let collection_id = create_test_collection(&CollectionMode::NFT, 1); let origin1 = Origin::signed(1); @@ -2180,8 +1872,6 @@ #[test] fn set_variable_on_chain_schema() { new_test_ext().execute_with(|| { - default_limits(); - let collection_id = create_test_collection(&CollectionMode::NFT, 1); let origin1 = Origin::signed(1); @@ -2209,8 +1899,6 @@ #[test] fn set_variable_meta_data_on_nft_token_stores_variable_meta_data() { new_test_ext().execute_with(|| { - default_limits(); - let collection_id = create_test_collection(&CollectionMode::NFT, 1); let origin1 = Origin::signed(1); @@ -2218,7 +1906,7 @@ let data = default_nft_data(); create_test_item(1, &data.into()); - let variable_data = b"test set_variable_meta_data method.".to_vec(); + let variable_data = b"test data".to_vec(); assert_ok!(TemplateModule::set_variable_meta_data( origin1, collection_id, @@ -2238,8 +1926,6 @@ #[test] fn set_variable_meta_data_on_re_fungible_token_stores_variable_meta_data() { new_test_ext().execute_with(|| { - default_limits(); - let collection_id = create_test_collection(&CollectionMode::ReFungible, 1); let origin1 = Origin::signed(1); @@ -2247,7 +1933,7 @@ let data = default_re_fungible_data(); create_test_item(1, &data.into()); - let variable_data = b"test set_variable_meta_data method.".to_vec(); + let variable_data = b"test data".to_vec(); assert_ok!(TemplateModule::set_variable_meta_data( origin1, collection_id, @@ -2267,8 +1953,6 @@ #[test] fn set_variable_meta_data_on_fungible_token_fails() { new_test_ext().execute_with(|| { - default_limits(); - let collection_id = create_test_collection(&CollectionMode::Fungible(3), 1); let origin1 = Origin::signed(1); @@ -2276,7 +1960,7 @@ let data = default_fungible_data(); create_test_item(1, &data.into()); - let variable_data = b"test set_variable_meta_data method.".to_vec(); + let variable_data = b"test data".to_vec(); assert_noop!( TemplateModule::set_variable_meta_data(origin1, collection_id, 1, variable_data), Error::::CantStoreMetadataInFungibleTokens @@ -2287,22 +1971,6 @@ #[test] fn set_variable_meta_data_on_nft_token_fails_for_big_data() { new_test_ext().execute_with(|| { - assert_ok!(TemplateModule::set_chain_limits( - RawOrigin::Root.into(), - ChainLimits { - collection_numbers_limit: default_collection_numbers_limit(), - account_token_ownership_limit: 10, - collections_admins_limit: 5, - custom_data_limit: 10, - nft_sponsor_transfer_timeout: 15, - fungible_sponsor_transfer_timeout: 15, - refungible_sponsor_transfer_timeout: 15, - const_on_chain_schema_limit: 1024, - offchain_schema_limit: 1024, - variable_on_chain_schema_limit: 1024, - } - )); - let collection_id = create_test_collection(&CollectionMode::NFT, 1); let origin1 = Origin::signed(1); @@ -2321,22 +1989,6 @@ #[test] fn set_variable_meta_data_on_re_fungible_token_fails_for_big_data() { new_test_ext().execute_with(|| { - assert_ok!(TemplateModule::set_chain_limits( - RawOrigin::Root.into(), - ChainLimits { - collection_numbers_limit: default_collection_numbers_limit(), - account_token_ownership_limit: 10, - collections_admins_limit: 5, - custom_data_limit: 10, - nft_sponsor_transfer_timeout: 15, - fungible_sponsor_transfer_timeout: 15, - refungible_sponsor_transfer_timeout: 15, - const_on_chain_schema_limit: 1024, - offchain_schema_limit: 1024, - variable_on_chain_schema_limit: 1024, - } - )); - let collection_id = create_test_collection(&CollectionMode::ReFungible, 1); let origin1 = Origin::signed(1); @@ -2355,8 +2007,6 @@ #[test] fn collection_transfer_flag_works() { new_test_ext().execute_with(|| { - default_limits(); - let origin1 = Origin::signed(1); let collection_id = create_test_collection(&CollectionMode::NFT, 1); @@ -2382,8 +2032,6 @@ #[test] fn collection_transfer_flag_works_neg() { new_test_ext().execute_with(|| { - default_limits(); - let origin1 = Origin::signed(1); let collection_id = create_test_collection(&CollectionMode::NFT, 1); --- a/primitives/nft/Cargo.toml +++ b/primitives/nft/Cargo.toml @@ -9,20 +9,28 @@ version = '0.9.0' [dependencies] -codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ['derive'] } -serde = { version = "1.0.119", features = ['derive'], default-features = false } +codec = { package = "parity-scale-codec", version = "2.2.0", default-features = false, features = ['derive'] } +serde = { version = "1.0.119", features = ['derive'], default-features = false, optional = true } +max-encoded-len = { default-features = false, features = ['derive'], version = '3.0.0', git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.8' } frame-support = { default-features = false, version = '3.0.0', git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.8' } frame-system = { default-features = false, version = '3.0.0', git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.8' } sp-core = { version = "3.0.0", default-features = false, git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.8' } +sp-std = { version = "3.0.0", default-features = false, git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.8' } sp-runtime = { version = "3.0.0", default-features = false, git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.8' } +derivative = "2.2.0" [features] default = ["std"] std = [ + "serde1", "serde/std", "codec/std", + "max-encoded-len/std", "frame-system/std", "frame-support/std", "sp-runtime/std", "sp-core/std", -] \ No newline at end of file + "sp-std/std", +] +serde1 = ["serde"] +limit-testing = [] \ No newline at end of file --- a/primitives/nft/src/lib.rs +++ b/primitives/nft/src/lib.rs @@ -1,11 +1,13 @@ #![cfg_attr(not(feature = "std"), no_std)] +#[cfg(feature = "serde")] pub use serde::{Serialize, Deserialize}; use sp_runtime::sp_std::prelude::Vec; use codec::{Decode, Encode}; +use max_encoded_len::MaxEncodedLen; pub use frame_support::{ - construct_runtime, decl_event, decl_module, decl_storage, decl_error, + BoundedVec, construct_runtime, decl_event, decl_module, decl_storage, decl_error, dispatch::DispatchResult, ensure, fail, parameter_types, traits::{ @@ -19,18 +21,54 @@ }, StorageValue, transactional, }; +use derivative::Derivative; pub const MAX_DECIMAL_POINTS: DecimalPoints = 30; pub const MAX_REFUNGIBLE_PIECES: u128 = 1_000_000_000_000_000_000_000; pub const MAX_SPONSOR_TIMEOUT: u32 = 10_368_000; pub const MAX_TOKEN_OWNERSHIP: u32 = 10_000_000; +pub const COLLECTION_NUMBER_LIMIT: u32 = if cfg!(not(feature = "limit-testing")) { + 100000 +} else { + 10 +}; +pub const CUSTOM_DATA_LIMIT: u32 = if cfg!(not(feature = "limit-testing")) { + 2048 +} else { + 10 +}; +pub const COLLECTION_ADMINS_LIMIT: u64 = 5; +pub const ACCOUNT_TOKEN_OWNERSHIP_LIMIT: u32 = if cfg!(not(feature = "limit-testing")) { + 1000000 +} else { + 10 +}; + +// Timeouts for item types in passed blocks +pub const NFT_SPONSOR_TRANSFER_TIMEOUT: u32 = 5; +pub const FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT: u32 = 5; +pub const REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT: u32 = 5; + +// Schema limits +pub const OFFCHAIN_SCHEMA_LIMIT: u32 = 1024; +pub const VARIABLE_ON_CHAIN_SCHEMA_LIMIT: u32 = 1024; +pub const CONST_ON_CHAIN_SCHEMA_LIMIT: u32 = 1024; + +/// How much items can be created per single +/// create_many call +pub const MAX_ITEMS_PER_BATCH: u32 = 200; + +parameter_types! { + pub const CustomDataLimit: u32 = CUSTOM_DATA_LIMIT; +} + pub type CollectionId = u32; pub type TokenId = u32; pub type DecimalPoints = u8; #[derive(Encode, Decode, Eq, Debug, Clone, PartialEq)] -#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))] pub enum CollectionMode { Invalid, NFT, @@ -61,7 +99,7 @@ } #[derive(Encode, Decode, Eq, Debug, Clone, PartialEq)] -#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))] pub enum AccessMode { Normal, WhiteList, @@ -73,7 +111,7 @@ } #[derive(Encode, Decode, Eq, Debug, Clone, PartialEq)] -#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))] pub enum SchemaVersion { ImageURL, Unique, @@ -85,14 +123,14 @@ } #[derive(Encode, Decode, Default, Debug, Clone, PartialEq)] -#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))] pub struct Ownership { pub owner: AccountId, pub fraction: u128, } #[derive(Encode, Decode, Debug, Clone, PartialEq)] -#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))] pub enum SponsorshipState { /// The fees are applied to the transaction sender Disabled, @@ -128,7 +166,7 @@ } #[derive(Encode, Decode, Clone, PartialEq)] -#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))] pub struct Collection { pub owner: T::AccountId, pub mode: CollectionMode, @@ -148,7 +186,7 @@ } #[derive(Encode, Decode, Debug, Clone, PartialEq)] -#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))] pub struct NftItemType { pub owner: AccountId, pub const_data: Vec, @@ -156,13 +194,13 @@ } #[derive(Encode, Decode, Default, Debug, Clone, PartialEq)] -#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))] pub struct FungibleItemType { pub value: u128, } #[derive(Encode, Decode, Debug, Clone, PartialEq)] -#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))] pub struct ReFungibleItemType { pub owner: Vec>, pub const_data: Vec, @@ -170,7 +208,7 @@ } #[derive(Encode, Decode, Debug, Clone, PartialEq)] -#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))] pub struct CollectionLimits { pub account_token_ownership_limit: u32, pub sponsored_data_size: u32, @@ -200,48 +238,72 @@ } } -#[derive(Encode, Decode, Default, Debug, Clone, PartialEq)] -#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] -pub struct ChainLimits { - pub collection_numbers_limit: u32, - pub account_token_ownership_limit: u32, - pub collections_admins_limit: u64, - pub custom_data_limit: u32, +/// BoundedVec doesn't supports serde +#[cfg(feature = "serde1")] +mod bounded_serde { + use core::convert::TryFrom; + use frame_support::{BoundedVec, traits::Get}; + use serde::{ + ser::{self, Serialize}, + de::{self, Deserialize, Error}, + }; + use sp_std::vec::Vec; - // Timeouts for item types in passed blocks - pub nft_sponsor_transfer_timeout: u32, - pub fungible_sponsor_transfer_timeout: u32, - pub refungible_sponsor_transfer_timeout: u32, + pub fn serialize(value: &BoundedVec, serializer: D) -> Result + where + D: ser::Serializer, + V: Serialize, + { + let vec: &Vec<_> = &value; + vec.serialize(serializer) + } - // Schema limits - pub offchain_schema_limit: u32, - pub variable_on_chain_schema_limit: u32, - pub const_on_chain_schema_limit: u32, + pub fn deserialize<'de, D, V, S>(deserializer: D) -> Result, D::Error> + where + D: de::Deserializer<'de>, + V: de::Deserialize<'de>, + S: Get, + { + // TODO: Implement custom visitor, which will limit vec size at parse time? Will serde only be used by chainspec? + let vec = >::deserialize(deserializer)?; + let len = vec.len(); + TryFrom::try_from(vec).map_err(|_| D::Error::invalid_length(len, &"lesser size")) + } } -#[derive(Encode, Decode, Default, Debug, Clone, PartialEq)] -#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +#[derive(Encode, Decode, MaxEncodedLen, Default, PartialEq, Clone, Derivative)] +#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))] +#[derivative(Debug)] pub struct CreateNftData { - pub const_data: Vec, - pub variable_data: Vec, + #[cfg_attr(feature = "serde1", serde(with = "bounded_serde"))] + #[derivative(Debug = "ignore")] + pub const_data: BoundedVec, + #[cfg_attr(feature = "serde1", serde(with = "bounded_serde"))] + #[derivative(Debug = "ignore")] + pub variable_data: BoundedVec, } -#[derive(Encode, Decode, Default, Debug, Clone, PartialEq)] -#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +#[derive(Encode, Decode, MaxEncodedLen, Default, Debug, Clone, PartialEq)] +#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))] pub struct CreateFungibleData { pub value: u128, } -#[derive(Encode, Decode, Default, Debug, Clone, PartialEq)] -#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +#[derive(Encode, Decode, MaxEncodedLen, Default, PartialEq, Clone, Derivative)] +#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))] +#[derivative(Debug)] pub struct CreateReFungibleData { - pub const_data: Vec, - pub variable_data: Vec, + #[cfg_attr(feature = "serde1", serde(with = "bounded_serde"))] + #[derivative(Debug = "ignore")] + pub const_data: BoundedVec, + #[cfg_attr(feature = "serde1", serde(with = "bounded_serde"))] + #[derivative(Debug = "ignore")] + pub variable_data: BoundedVec, pub pieces: u128, } -#[derive(Encode, Decode, Debug, Clone, PartialEq)] -#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +#[derive(Encode, Decode, MaxEncodedLen, PartialEq, Clone, Debug)] +#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))] pub enum CreateItemData { NFT(CreateNftData), Fungible(CreateFungibleData), --- a/runtime/Cargo.toml +++ b/runtime/Cargo.toml @@ -31,6 +31,7 @@ ] std = [ 'codec/std', + 'max-encoded-len/std', 'cumulus-pallet-aura-ext/std', 'cumulus-pallet-parachain-system/std', 'cumulus-pallet-xcm/std', @@ -84,6 +85,10 @@ 'xcm-builder/std', 'xcm-executor/std', ] +limit-testing = [ + 'pallet-nft/limit-testing', + 'nft-data-structs/limit-testing', +] ################################################################################ # Substrate Dependencies @@ -378,6 +383,8 @@ # local dependencies [dependencies] +max-encoded-len = { default-features = false, features = ['derive'], version = '3.0.0', git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.8' } +derivative = "2.2.0" pallet-nft = { path = '../pallets/nft', default-features = false, version = '3.0.0' } pallet-inflation = { path = '../pallets/inflation', default-features = false, version = '3.0.0' } nft-data-structs = { path = '../primitives/nft', default-features = false, version = '0.9.0' } --- a/runtime/src/chain_extension.rs +++ b/runtime/src/chain_extension.rs @@ -6,6 +6,8 @@ // use codec::{Decode, Encode}; +use max_encoded_len::MaxEncodedLen; +use derivative::Derivative; pub use pallet_contracts::chain_extension::RetVal; use pallet_contracts::chain_extension::{ @@ -19,61 +21,63 @@ pub use pallet_nft::*; use pallet_nft::CrossAccountId; use nft_data_structs::*; - -use crate::Vec; /// Create item parameters -#[derive(Debug, PartialEq, Encode, Decode)] -pub struct NFTExtCreateItem { - pub owner: ::AccountId, +#[derive(Debug, PartialEq, Encode, Decode, MaxEncodedLen)] +pub struct NFTExtCreateItem { + pub owner: AccountId, pub collection_id: u32, pub data: CreateItemData, } /// Transfer parameters -#[derive(Debug, PartialEq, Encode, Decode)] -pub struct NFTExtTransfer { - pub recipient: ::AccountId, +#[derive(Debug, PartialEq, Encode, Decode, MaxEncodedLen)] +pub struct NFTExtTransfer { + pub recipient: AccountId, pub collection_id: u32, pub token_id: u32, pub amount: u128, } -#[derive(Debug, PartialEq, Encode, Decode)] -pub struct NFTExtCreateMultipleItems { - pub owner: ::AccountId, +#[derive(Derivative, PartialEq, Encode, Decode, MaxEncodedLen)] +#[derivative(Debug)] +pub struct NFTExtCreateMultipleItems { + pub owner: AccountId, pub collection_id: u32, - pub data: Vec, + #[derivative(Debug = "ignore")] + pub data: BoundedVec, } -#[derive(Debug, PartialEq, Encode, Decode)] -pub struct NFTExtApprove { - pub spender: ::AccountId, +#[derive(Debug, PartialEq, Encode, Decode, MaxEncodedLen)] +pub struct NFTExtApprove { + pub spender: AccountId, pub collection_id: u32, pub item_id: u32, pub amount: u128, } -#[derive(Debug, PartialEq, Encode, Decode)] -pub struct NFTExtTransferFrom { - pub owner: ::AccountId, - pub recipient: ::AccountId, +#[derive(Debug, PartialEq, Encode, Decode, MaxEncodedLen)] +pub struct NFTExtTransferFrom { + pub owner: AccountId, + pub recipient: AccountId, pub collection_id: u32, pub item_id: u32, pub amount: u128, } -#[derive(Debug, PartialEq, Encode, Decode)] +#[derive(Derivative, PartialEq, Encode, Decode, MaxEncodedLen)] +#[derivative(Debug)] pub struct NFTExtSetVariableMetaData { pub collection_id: u32, pub item_id: u32, - pub data: Vec, + #[derivative(Debug = "ignore")] + pub data: BoundedVec, } -#[derive(Debug, PartialEq, Encode, Decode)] -pub struct NFTExtToggleWhiteList { +#[derive(Debug, PartialEq, Encode, Decode, MaxEncodedLen)] +pub struct NFTExtToggleWhiteList { pub collection_id: u32, - pub address: ::AccountId, + pub address: AccountId, pub whitelisted: bool, } @@ -82,6 +86,8 @@ pub type NftWeightInfoOf = ::WeightInfo; +pub type AccountIdOf = ::AccountId; + impl ChainExtension for NFTExtension { fn call(func_id: u32, env: Environment) -> Result where @@ -93,7 +99,7 @@ match func_id { 0 => { let mut env = env.buf_in_buf_out(); - let input: NFTExtTransfer = env.read_as()?; + let input: NFTExtTransfer> = env.read_as()?; env.charge_weight(NftWeightInfoOf::::transfer())?; let collection = pallet_nft::Module::::get_collection(input.collection_id)?; @@ -106,13 +112,13 @@ input.amount, )?; - pallet_nft::Module::::submit_logs(collection)?; + collection.submit_logs()?; Ok(RetVal::Converging(0)) } 1 => { // Create Item let mut env = env.buf_in_buf_out(); - let input: NFTExtCreateItem = env.read_as()?; + let input: NFTExtCreateItem> = env.read_as()?; env.charge_weight(NftWeightInfoOf::::create_item(input.data.data_size()))?; let collection = pallet_nft::Module::::get_collection(input.collection_id)?; @@ -124,13 +130,13 @@ input.data, )?; - pallet_nft::Module::::submit_logs(collection)?; + collection.submit_logs()?; Ok(RetVal::Converging(0)) } 2 => { // Create multiple items let mut env = env.buf_in_buf_out(); - let input: NFTExtCreateMultipleItems = env.read_as()?; + let input: NFTExtCreateMultipleItems> = env.read_as()?; env.charge_weight(NftWeightInfoOf::::create_item( input.data.iter().map(|i| i.data_size()).sum(), ))?; @@ -141,16 +147,16 @@ &C::CrossAccountId::from_sub(env.ext().address().clone()), &collection, &C::CrossAccountId::from_sub(input.owner), - input.data, + input.data.into_inner(), )?; - pallet_nft::Module::::submit_logs(collection)?; + collection.submit_logs()?; Ok(RetVal::Converging(0)) } 3 => { // Approve let mut env = env.buf_in_buf_out(); - let input: NFTExtApprove = env.read_as()?; + let input: NFTExtApprove> = env.read_as()?; env.charge_weight(NftWeightInfoOf::::approve())?; let collection = pallet_nft::Module::::get_collection(input.collection_id)?; @@ -163,13 +169,13 @@ input.amount, )?; - pallet_nft::Module::::submit_logs(collection)?; + collection.submit_logs()?; Ok(RetVal::Converging(0)) } 4 => { // Transfer from let mut env = env.buf_in_buf_out(); - let input: NFTExtTransferFrom = env.read_as()?; + let input: NFTExtTransferFrom> = env.read_as()?; env.charge_weight(NftWeightInfoOf::::transfer_from())?; let collection = pallet_nft::Module::::get_collection(input.collection_id)?; @@ -183,7 +189,7 @@ input.amount, )?; - pallet_nft::Module::::submit_logs(collection)?; + collection.submit_logs()?; Ok(RetVal::Converging(0)) } 5 => { @@ -198,16 +204,16 @@ &C::CrossAccountId::from_sub(env.ext().address().clone()), &collection, input.item_id, - input.data, + input.data.into_inner(), )?; - pallet_nft::Module::::submit_logs(collection)?; + collection.submit_logs()?; Ok(RetVal::Converging(0)) } 6 => { // Toggle whitelist let mut env = env.buf_in_buf_out(); - let input: NFTExtToggleWhiteList = env.read_as()?; + let input: NFTExtToggleWhiteList> = env.read_as()?; env.charge_weight(NftWeightInfoOf::::add_to_white_list())?; let collection = pallet_nft::Module::::get_collection(input.collection_id)?; @@ -219,7 +225,7 @@ input.whitelisted, )?; - pallet_nft::Module::::submit_logs(collection)?; + collection.submit_logs()?; Ok(RetVal::Converging(0)) } _ => Err(DispatchError::Other("unknown chain_extension func_id")), --- a/runtime/src/lib.rs +++ b/runtime/src/lib.rs @@ -72,7 +72,6 @@ use sp_runtime::{ traits::{Dispatchable}, }; -// use pallet_contracts::chain_extension::UncheckedFrom; // pub use pallet_timestamp::Call as TimestampCall; pub use sp_consensus_aura::sr25519::AuthorityId as AuraId; @@ -419,7 +418,7 @@ type DepositPerStorageItem = DepositPerStorageItem; type RentFraction = RentFraction; type SurchargeReward = SurchargeReward; - type WeightPrice = pallet_transaction_payment::Module; + type WeightPrice = pallet_transaction_payment::Pallet; type WeightInfo = pallet_contracts::weights::SubstrateWeight; type ChainExtension = NFTExtension; type DeletionQueueDepth = DeletionQueueDepth; --- a/runtime/src/nft_weights.rs +++ b/runtime/src/nft_weights.rs @@ -123,11 +123,6 @@ .saturating_add(DbWeight::get().reads(2_u64)) .saturating_add(DbWeight::get().writes(1_u64)) } - fn set_chain_limits() -> Weight { - 1_300_000_u64 - .saturating_add(DbWeight::get().reads(0_u64)) - .saturating_add(DbWeight::get().writes(1_u64)) - } fn set_contract_sponsoring_rate_limit() -> Weight { 3_500_000_u64 .saturating_add(DbWeight::get().reads(0_u64)) --- a/tests/package.json +++ b/tests/package.json @@ -4,9 +4,9 @@ "description": "Substrate Nft tests", "main": "", "devDependencies": { - "@polkadot/dev": "0.62.43", - "@polkadot/ts": "0.3.89", - "@polkadot/typegen": "5.0.1", + "@polkadot/dev": "0.62.60", + "@polkadot/ts": "0.4.4", + "@polkadot/typegen": "5.5.1", "@types/chai": "^4.2.17", "@types/chai-as-promised": "^7.1.3", "@types/mocha": "^8.2.2", @@ -23,7 +23,7 @@ "scripts": { "lint": "eslint --ext .ts,.js src/", "fix": "eslint --ext .ts,.js src/ --fix", - "test": "mocha --timeout 9999999 -r ts-node/register ./**/*.test.ts ./**/eth/**/*.test.ts", + "test": "mocha --timeout 9999999 -r ts-node/register './**/*.test.ts'", "testEth": "mocha --timeout 9999999 -r ts-node/register ./**/eth/**/*.test.ts", "load": "mocha --timeout 9999999 -r ts-node/register ./**/*.load.ts", "loadTransfer": "ts-node src/transfer.nload.ts", @@ -66,8 +66,9 @@ "license": "SEE LICENSE IN ../LICENSE", "homepage": "", "dependencies": { - "@polkadot/api": "5.0.1", - "@polkadot/api-contract": "5.0.1", + "@polkadot/api": "5.5.1", + "@polkadot/api-contract": "5.5.1", + "@polkadot/util-crypto": "^7.2.1", "bignumber.js": "^9.0.1", "chai-as-promised": "^7.1.1", "solc": "^0.8.6", --- a/tests/src/addCollectionAdmin.test.ts +++ b/tests/src/addCollectionAdmin.test.ts @@ -117,8 +117,7 @@ ]; const collectionId = await createCollectionExpectSuccess(); - const chainLimit = await api.query.nft.chainLimit() as unknown as { CollectionAdminsLimit: BN }; - const chainAdminLimit = chainLimit.CollectionAdminsLimit.toNumber(); + const chainAdminLimit = (api.consts.nft.collectionAdminsLimit as any).toNumber(); expect(chainAdminLimit).to.be.equal(5); for (let i = 0; i < chainAdminLimit; i++) { --- a/tests/src/collision-tests/adminLimitsOff.test.ts +++ b/tests/src/collision-tests/adminLimitsOff.test.ts @@ -34,8 +34,7 @@ await usingApi(async (api) => { const collectionId = await createCollectionExpectSuccess(); - const chainLimit = await api.query.nft.chainLimit() as unknown as { CollectionAdminsLimit: BN }; - const chainAdminLimit = chainLimit.CollectionAdminsLimit.toNumber(); + const chainAdminLimit = (api.consts.nft.collectionAdminsLimit as any).toNumber(); expect(chainAdminLimit).to.be.equal(5); const changeAdminTx1 = api.tx.nft.addCollectionAdmin(collectionId, Eve.address); --- /dev/null +++ b/tests/src/eth/base.test.ts @@ -0,0 +1,22 @@ + +import { createEthAccount, createEthAccountWithBalance, deployFlipper, ethBalanceViaSub, GAS_ARGS, itWeb3, recordEthFee } from './util/helpers'; +import { expect } from 'chai'; +import { UNIQUE } from '../util/helpers'; + +describe('Contract calls', () => { + itWeb3('Call of simple contract fee is less than 0.2 UNQ', async ({ web3, api }) => { + const deployer = await createEthAccountWithBalance(api, web3); + const flipper = await deployFlipper(web3 as any, deployer); + + const cost = await recordEthFee(api, deployer, () => flipper.methods.flip().send({from: deployer})); + expect(cost < BigInt(0.2 * Number(UNIQUE))).to.be.true; + }); + + itWeb3('Balance transfer fee is less than 0.2 UNQ', async ({ web3, api }) => { + const userA = await createEthAccountWithBalance(api, web3); + const userB = createEthAccount(web3); + + const cost = await recordEthFee(api, userA, () => web3.eth.sendTransaction({ from: userA, to: userB, value: '1000000', ...GAS_ARGS })); + expect(cost - await ethBalanceViaSub(api, userB) < BigInt(0.2 * Number(UNIQUE))).to.be.true; + }); +}); \ No newline at end of file --- /dev/null +++ b/tests/src/eth/crossTransfer.test.ts @@ -0,0 +1,88 @@ +// +// This file is subject to the terms and conditions defined in +// file 'LICENSE', which is part of this source code package. +// + +import privateKey from '../substrate/privateKey'; +import { createCollectionExpectSuccess, + createFungibleItemExpectSuccess, + transferExpectSuccess, + transferFromExpectSuccess, + createItemExpectSuccess } from '../util/helpers'; +import { collectionIdToAddress, + createEthAccountWithBalance, + subToEth, + GAS_ARGS, itWeb3 } from './util/helpers'; +import fungibleAbi from './fungibleAbi.json'; +import nonFungibleAbi from './nonFungibleAbi.json'; + +describe('Token transfer between substrate address and EVM address. Fungible', () => { + itWeb3('The private key X create a substrate address. Alice sends a token to the corresponding EVM address, and X can send it to Bob in the substrate', async () => { + const collection = await createCollectionExpectSuccess({ + name: 'token name', + mode: { type: 'Fungible', decimalPoints: 0 }, + }); + const alice = privateKey('//Alice'); + const bob = privateKey('//Bob'); + const charlie = privateKey('//Charlie'); + await createFungibleItemExpectSuccess(alice, collection, { Value: 200n }, { substrate: alice.address }); + await transferExpectSuccess(collection, 0, alice, {ethereum: subToEth(charlie.address)} , 200, 'Fungible'); + await transferFromExpectSuccess(collection, 0, alice, {ethereum: subToEth(charlie.address)}, charlie, 50, 'Fungible'); + await transferExpectSuccess(collection, 0, charlie, bob, 50, 'Fungible'); + }); + + itWeb3('The private key X create a EVM address. Alice sends a token to the substrate address corresponding to this EVM address, and X can send it to Bob in the EVM', async ({ api, web3 }) => { + const collection = await createCollectionExpectSuccess({ + name: 'token name', + mode: { type: 'Fungible', decimalPoints: 0 }, + }); + const alice = privateKey('//Alice'); + const bob = privateKey('//Bob'); + const bobProxy = await createEthAccountWithBalance(api, web3); + const aliceProxy = await createEthAccountWithBalance(api, web3); + + await createFungibleItemExpectSuccess(alice, collection, { Value: 200n }, alice.address); + await transferExpectSuccess(collection, 0, alice, { ethereum: aliceProxy } , 200, 'Fungible'); + const address = collectionIdToAddress(collection); + const contract = new web3.eth.Contract(fungibleAbi as any, address, {from: aliceProxy, ...GAS_ARGS}); + + await contract.methods.transfer(bobProxy, 50).send({ from: aliceProxy }); + await transferFromExpectSuccess(collection, 0, alice, {ethereum: bobProxy}, bob, 50, 'Fungible'); + await transferExpectSuccess(collection, 0, bob, alice, 50, 'Fungible'); + }); +}); + +describe('Token transfer between substrate address and EVM address. NFT', () => { + itWeb3('The private key X create a substrate address. Alice sends a token to the corresponding EVM address, and X can send it to Bob in the substrate', async () => { + const collection = await createCollectionExpectSuccess({ + name: 'token name', + mode: { type: 'NFT' }, + }); + const alice = privateKey('//Alice'); + const bob = privateKey('//Bob'); + const charlie = privateKey('//Charlie'); + const tokenId = await createItemExpectSuccess(alice, collection, 'NFT', { substrate: alice.address }); + await transferExpectSuccess(collection, tokenId, alice, { ethereum: subToEth(charlie.address) }, 1, 'NFT'); + await transferFromExpectSuccess(collection, tokenId, alice, {ethereum: subToEth(charlie.address)}, charlie, 1, 'NFT'); + await transferExpectSuccess(collection, tokenId, charlie, bob, 1, 'NFT'); + }); + + itWeb3('The private key X create a EVM address. Alice sends a token to the substrate address corresponding to this EVM address, and X can send it to Bob in the EVM', async ({ api, web3 }) => { + const collection = await createCollectionExpectSuccess({ + name: 'token name', + mode: { type: 'NFT' }, + }); + const alice = privateKey('//Alice'); + const bob = privateKey('//Bob'); + const charlie = privateKey('//Charlie'); + const bobProxy = await createEthAccountWithBalance(api, web3); + const aliceProxy = await createEthAccountWithBalance(api, web3); + const tokenId = await createItemExpectSuccess(alice, collection, 'NFT', { substrate: alice.address }); + await transferExpectSuccess(collection, tokenId, alice, { ethereum: aliceProxy } , 1, 'NFT'); + const address = collectionIdToAddress(collection); + const contract = new web3.eth.Contract(nonFungibleAbi as any, address, {from: aliceProxy, ...GAS_ARGS}); + await contract.methods.transfer(bobProxy, 1).send({ from: aliceProxy }); + await transferFromExpectSuccess(collection, tokenId, alice, {ethereum: bobProxy}, bob, 1, 'NFT'); + await transferExpectSuccess(collection, tokenId, bob, charlie, 1, 'NFT'); + }); +}); \ No newline at end of file --- a/tests/src/eth/fungible.test.ts +++ b/tests/src/eth/fungible.test.ts @@ -4,8 +4,8 @@ // import privateKey from '../substrate/privateKey'; -import { approveExpectSuccess, createCollectionExpectSuccess, createFungibleItemExpectSuccess, transferExpectSuccess, transferFromExpectSuccess } from '../util/helpers'; -import { collectionIdToAddress, createEthAccount, createEthAccountWithBalance, GAS_ARGS, itWeb3, normalizeEvents, recordEvents, subToEth, transferBalanceToEth } from './util/helpers'; +import { approveExpectSuccess, createCollectionExpectSuccess, createFungibleItemExpectSuccess, transferExpectSuccess, transferFromExpectSuccess, UNIQUE } from '../util/helpers'; +import { collectionIdToAddress, createEthAccount, createEthAccountWithBalance, GAS_ARGS, itWeb3, normalizeEvents, recordEthFee, recordEvents, subToEth, transferBalanceToEth } from './util/helpers'; import fungibleAbi from './fungibleAbi.json'; import { expect } from 'chai'; @@ -192,6 +192,64 @@ }); }); +describe('Fungible: Fees', () => { + itWeb3('approve() call fee is less than 0.2UNQ', async ({ web3, api }) => { + const collection = await createCollectionExpectSuccess({ + mode: { type: 'Fungible', decimalPoints: 0 }, + }); + const alice = privateKey('//Alice'); + + const owner = await createEthAccountWithBalance(api, web3); + const spender = createEthAccount(web3); + + await createFungibleItemExpectSuccess(alice, collection, { Value: 200n }, { ethereum: owner }); + + const address = collectionIdToAddress(collection); + const contract = new web3.eth.Contract(fungibleAbi as any, address, { from: owner, ...GAS_ARGS }); + + const cost = await recordEthFee(api, owner, () => contract.methods.approve(spender, 100).send({ from: owner })); + expect(cost < BigInt(0.2 * Number(UNIQUE))); + }); + + itWeb3('transferFrom() call fee is less than 0.2UNQ', async ({ web3, api }) => { + const collection = await createCollectionExpectSuccess({ + mode: {type: 'Fungible', decimalPoints: 0}, + }); + const alice = privateKey('//Alice'); + + const owner = await createEthAccountWithBalance(api, web3); + const spender = await createEthAccountWithBalance(api, web3); + + await createFungibleItemExpectSuccess(alice, collection, { Value: 200n }, { ethereum: owner }); + + const address = collectionIdToAddress(collection); + const contract = new web3.eth.Contract(fungibleAbi as any, address, { from: owner, ...GAS_ARGS }); + + await contract.methods.approve(spender, 100).send({ from: owner }); + + const cost = await recordEthFee(api, spender, () => contract.methods.transferFrom(owner, spender, 100).send({ from: spender })); + expect(cost < BigInt(0.2 * Number(UNIQUE))); + }); + + itWeb3('transfer() call fee is less than 0.2UNQ', async ({ web3, api }) => { + const collection = await createCollectionExpectSuccess({ + mode: { type: 'Fungible', decimalPoints: 0 }, + }); + const alice = privateKey('//Alice'); + + const owner = await createEthAccountWithBalance(api, web3); + const receiver = createEthAccount(web3); + + await createFungibleItemExpectSuccess(alice, collection, { Value: 200n }, { ethereum: owner }); + + const address = collectionIdToAddress(collection); + const contract = new web3.eth.Contract(fungibleAbi as any, address, { from: owner, ...GAS_ARGS }); + + const cost = await recordEthFee(api, owner, () => contract.methods.transfer(receiver, 100).send({ from: owner })); + expect(cost < BigInt(0.2 * Number(UNIQUE))); + }); +}); + describe('Fungible: Substrate calls', () => { itWeb3('Events emitted for approve()', async ({ web3 }) => { const collection = await createCollectionExpectSuccess({ --- a/tests/src/eth/helpersSmoke.test.ts +++ b/tests/src/eth/helpersSmoke.test.ts @@ -1,26 +1,24 @@ import { expect } from 'chai'; import waitNewBlocks from '../substrate/wait-new-blocks'; -import { createEthAccountWithBalance, deployFlipper, itWeb3, usingWeb3Http, contractHelpers } from './util/helpers'; +import { createEthAccountWithBalance, deployFlipper, itWeb3, contractHelpers } from './util/helpers'; -itWeb3('Contract owner is recorded', async ({ api, web3 }) => { - await usingWeb3Http(async web3Http => { - const owner = await createEthAccountWithBalance(api, web3Http); +describe('Helpers sanity check', () => { + itWeb3('Contract owner is recorded', async ({ api, web3 }) => { + const owner = await createEthAccountWithBalance(api, web3); - const flipper = await deployFlipper(web3Http, owner); + const flipper = await deployFlipper(web3, owner); await waitNewBlocks(api, 1); expect(await contractHelpers(web3, owner).methods.contractOwner(flipper.options.address).call()).to.be.equal(owner); }); -}); -itWeb3('Flipper is working', async({api}) => { - await usingWeb3Http(async web3Http => { - const owner = await createEthAccountWithBalance(api, web3Http); - const flipper = await deployFlipper(web3Http, owner); + itWeb3('Flipper is working', async ({ api, web3 }) => { + const owner = await createEthAccountWithBalance(api, web3); + const flipper = await deployFlipper(web3, owner); await waitNewBlocks(api, 1); expect(await flipper.methods.getValue().call()).to.be.false; - await flipper.methods.flip().send({from: owner}); + await flipper.methods.flip().send({ from: owner }); await waitNewBlocks(api, 1); expect(await flipper.methods.getValue().call()).to.be.true; }); --- a/tests/src/eth/nonFungible.test.ts +++ b/tests/src/eth/nonFungible.test.ts @@ -4,11 +4,13 @@ // import privateKey from '../substrate/privateKey'; -import { approveExpectSuccess, createCollectionExpectSuccess, createItemExpectSuccess, transferExpectSuccess, transferFromExpectSuccess } from '../util/helpers'; -import { collectionIdToAddress, createEthAccount, createEthAccountWithBalance, GAS_ARGS, itWeb3, normalizeEvents, recordEvents, subToEth, transferBalanceToEth } from './util/helpers'; +import { approveExpectSuccess, burnItemExpectSuccess, createCollectionExpectSuccess, createItemExpectSuccess, transferExpectSuccess, transferFromExpectSuccess, UNIQUE } from '../util/helpers'; +import { collectionIdToAddress, createEthAccount, createEthAccountWithBalance, GAS_ARGS, itWeb3, normalizeEvents, recordEthFee, recordEvents, subToEth, transferBalanceToEth } from './util/helpers'; +import { evmToAddress } from '@polkadot/util-crypto'; import nonFungibleAbi from './nonFungibleAbi.json'; import { expect } from 'chai'; import waitNewBlocks from '../substrate/wait-new-blocks'; +import { submitTransactionAsync } from '../substrate/substrate-api'; describe('NFT: Information getting', () => { itWeb3('totalSupply', async ({ api, web3 }) => { @@ -64,6 +66,78 @@ }); describe('NFT: Plain calls', () => { + itWeb3('Can perform mint()', async ({ web3, api }) => { + const collection = await createCollectionExpectSuccess({ + mode: { type: 'NFT' }, + }); + const alice = privateKey('//Alice'); + + const caller = await createEthAccountWithBalance(api, web3); + const changeAdminTx = api.tx.nft.addCollectionAdmin(collection, { ethereum: caller }); + await submitTransactionAsync(alice, changeAdminTx); + const receiver = createEthAccount(web3); + + const address = collectionIdToAddress(collection); + const contract = new web3.eth.Contract(nonFungibleAbi as any, address, {from: caller, ...GAS_ARGS}); + + { + const nextTokenId = await contract.methods.nextTokenId().call(); + expect(nextTokenId).to.be.equal('1'); + const result = await contract.methods.mintWithTokenURI( + receiver, + nextTokenId, + 'Test URI', + ).send({from: caller}); + const events = normalizeEvents(result.events); + + expect(events).to.be.deep.equal([ + { + address, + event: 'Transfer', + args: { + from: '0x0000000000000000000000000000000000000000', + to: receiver, + tokenId: nextTokenId, + }, + }, + ]); + + await waitNewBlocks(api, 1); + expect(await contract.methods.tokenURI(nextTokenId).call()).to.be.equal('Test URI'); + } + }); + + itWeb3('Can perform burn()', async ({ web3, api }) => { + const collection = await createCollectionExpectSuccess({ + mode: {type: 'NFT'}, + }); + const alice = privateKey('//Alice'); + + const owner = await createEthAccountWithBalance(api, web3); + + const tokenId = await createItemExpectSuccess(alice, collection, 'NFT', { ethereum: owner }); + + const address = collectionIdToAddress(collection); + const contract = new web3.eth.Contract(nonFungibleAbi as any, address, {from: owner, ...GAS_ARGS}); + + { + const result = await contract.methods.burn(tokenId).send({ from: owner }); + const events = normalizeEvents(result.events); + + expect(events).to.be.deep.equal([ + { + address, + event: 'Transfer', + args: { + from: owner, + to: '0x0000000000000000000000000000000000000000', + tokenId: tokenId.toString(), + }, + }, + ]); + } + }); + itWeb3('Can perform approve()', async ({ web3, api }) => { const collection = await createCollectionExpectSuccess({ mode: { type: 'NFT' }, @@ -192,7 +266,119 @@ }); }); +describe('NFT: Fees', () => { + itWeb3('approve() call fee is less than 0.2UNQ', async ({ web3, api }) => { + const collection = await createCollectionExpectSuccess({ + mode: { type: 'NFT' }, + }); + const alice = privateKey('//Alice'); + + const owner = await createEthAccountWithBalance(api, web3); + const spender = createEthAccount(web3); + + const tokenId = await createItemExpectSuccess(alice, collection, 'NFT', { ethereum: owner }); + + const address = collectionIdToAddress(collection); + const contract = new web3.eth.Contract(nonFungibleAbi as any, address, { from: owner, ...GAS_ARGS }); + + const cost = await recordEthFee(api, owner, () => contract.methods.approve(spender, tokenId).send({ from: owner })); + expect(cost < BigInt(0.2 * Number(UNIQUE))); + }); + + itWeb3('transferFrom() call fee is less than 0.2UNQ', async ({ web3, api }) => { + const collection = await createCollectionExpectSuccess({ + mode: { type: 'NFT' }, + }); + const alice = privateKey('//Alice'); + + const owner = await createEthAccountWithBalance(api, web3); + const spender = await createEthAccountWithBalance(api, web3); + + const tokenId = await createItemExpectSuccess(alice, collection, 'NFT', { ethereum: owner }); + + const address = collectionIdToAddress(collection); + const contract = new web3.eth.Contract(nonFungibleAbi as any, address, { from: owner, ...GAS_ARGS }); + + await contract.methods.approve(spender, tokenId).send({ from: owner }); + + const cost = await recordEthFee(api, spender, () => contract.methods.transferFrom(owner, spender, tokenId).send({ from: spender })); + expect(cost < BigInt(0.2 * Number(UNIQUE))); + }); + + itWeb3('transfer() call fee is less than 0.2UNQ', async ({ web3, api }) => { + const collection = await createCollectionExpectSuccess({ + mode: { type: 'NFT' }, + }); + const alice = privateKey('//Alice'); + + const owner = await createEthAccountWithBalance(api, web3); + const receiver = createEthAccount(web3); + + const tokenId = await createItemExpectSuccess(alice, collection, 'NFT', { ethereum: owner }); + + const address = collectionIdToAddress(collection); + const contract = new web3.eth.Contract(nonFungibleAbi as any, address, { from: owner, ...GAS_ARGS }); + + const cost = await recordEthFee(api, owner, () => contract.methods.transfer(receiver, tokenId).send({ from: owner })); + expect(cost < BigInt(0.2 * Number(UNIQUE))); + }); +}); + describe('NFT: Substrate calls', () => { + itWeb3('Events emitted for mint()', async ({ web3 }) => { + const collection = await createCollectionExpectSuccess({ + mode: { type: 'NFT' }, + }); + const alice = privateKey('//Alice'); + + const address = collectionIdToAddress(collection); + const contract = new web3.eth.Contract(nonFungibleAbi as any, address); + + let tokenId: number; + const events = await recordEvents(contract, async () => { + tokenId = await createItemExpectSuccess(alice, collection, 'NFT'); + }); + + expect(events).to.be.deep.equal([ + { + address, + event: 'Transfer', + args: { + from: '0x0000000000000000000000000000000000000000', + to: subToEth(alice.address), + tokenId: tokenId!.toString(), + }, + }, + ]); + }); + + itWeb3('Events emitted for burn()', async ({ web3 }) => { + const collection = await createCollectionExpectSuccess({ + mode: { type: 'NFT' }, + }); + const alice = privateKey('//Alice'); + + const address = collectionIdToAddress(collection); + const contract = new web3.eth.Contract(nonFungibleAbi as any, address); + + const tokenId = await createItemExpectSuccess(alice, collection, 'NFT'); + const events = await recordEvents(contract, async () => { + await burnItemExpectSuccess(alice, collection, tokenId); + }); + + expect(events).to.be.deep.equal([ + { + address, + event: 'Transfer', + args: { + from: subToEth(alice.address), + to: '0x0000000000000000000000000000000000000000', + tokenId: tokenId.toString(), + }, + }, + ]); + }); + itWeb3('Events emitted for approve()', async ({ web3 }) => { const collection = await createCollectionExpectSuccess({ mode: { type: 'NFT' }, @@ -284,4 +470,4 @@ }, ]); }); -}); \ No newline at end of file +}); --- a/tests/src/eth/nonFungibleAbi.json +++ b/tests/src/eth/nonFungibleAbi.json @@ -50,6 +50,12 @@ "type": "event" }, { + "anonymous": true, + "inputs": [], + "name": "MintingFinished", + "type": "event" + }, + { "anonymous": false, "inputs": [ { @@ -89,7 +95,7 @@ ], "name": "approve", "outputs": [], - "stateMutability": "payable", + "stateMutability": "nonpayable", "type": "function" }, { @@ -119,6 +125,32 @@ "type": "uint256" } ], + "name": "burn", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "finishMinting", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], "name": "getApproved", "outputs": [ { @@ -146,11 +178,77 @@ "name": "isApprovedForAll", "outputs": [ { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [ + { "internalType": "bool", "name": "", "type": "bool" } ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "internalType": "string", + "name": "tokenURI", + "type": "string" + } + ], + "name": "mintWithTokenURI", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "mintingFinished", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], "stateMutability": "view", "type": "function" }, @@ -160,7 +258,7 @@ "outputs": [ { "internalType": "string", - "name": "res_name", + "name": "", "type": "string" } ], @@ -168,6 +266,19 @@ "type": "function" }, { + "inputs": [], + "name": "nextTokenId", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { "inputs": [ { "internalType": "uint256", @@ -206,7 +317,7 @@ ], "name": "safeTransferFrom", "outputs": [], - "stateMutability": "payable", + "stateMutability": "nonpayable", "type": "function" }, { @@ -232,9 +343,9 @@ "type": "bytes" } ], - "name": "safeTransferFrom", + "name": "safeTransferFromWithData", "outputs": [], - "stateMutability": "payable", + "stateMutability": "nonpayable", "type": "function" }, { @@ -258,9 +369,9 @@ { "inputs": [ { - "internalType": "bytes4", - "name": "interfaceID", - "type": "bytes4" + "internalType": "uint32", + "name": "interfaceId", + "type": "uint32" } ], "name": "supportsInterface", @@ -271,7 +382,7 @@ "type": "bool" } ], - "stateMutability": "pure", + "stateMutability": "view", "type": "function" }, { @@ -280,7 +391,7 @@ "outputs": [ { "internalType": "string", - "name": "res_symbol", + "name": "", "type": "string" } ], @@ -366,11 +477,6 @@ "inputs": [ { "internalType": "address", - "name": "from", - "type": "address" - }, - { - "internalType": "address", "name": "to", "type": "address" }, @@ -380,15 +486,20 @@ "type": "uint256" } ], - "name": "transferFrom", + "name": "transfer", "outputs": [], - "stateMutability": "payable", + "stateMutability": "nonpayable", "type": "function" }, { "inputs": [ { "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", "name": "to", "type": "address" }, @@ -398,9 +509,9 @@ "type": "uint256" } ], - "name": "transfer", + "name": "transferFrom", "outputs": [], - "stateMutability": "payable", + "stateMutability": "nonpayable", "type": "function" } ] \ No newline at end of file --- /dev/null +++ b/tests/src/eth/payable.test.ts @@ -0,0 +1,98 @@ +import { expect } from 'chai'; +import privateKey from '../substrate/privateKey'; +import { submitTransactionAsync } from '../substrate/substrate-api'; +import waitNewBlocks from '../substrate/wait-new-blocks'; +import { createEthAccountWithBalance, deployCollector, GAS_ARGS, itWeb3, subToEth } from './util/helpers'; +import {evmToAddress} from '@polkadot/util-crypto'; +import { getGenericResult } from '../util/helpers'; +import { getBalanceSingle, transferBalanceExpectSuccess } from '../substrate/get-balance'; + +describe('EVM payable contracts', ()=>{ + itWeb3('Evm contract can receive wei from eth account', async ({api, web3}) => { + const deployer = await createEthAccountWithBalance(api, web3); + const contract = await deployCollector(web3, deployer); + + await web3.eth.sendTransaction({from: deployer, to: contract.options.address, value: '10000', ...GAS_ARGS}); + await waitNewBlocks(api, 1); + + expect(await contract.methods.getCollected().call()).to.be.equal('10000'); + }); + + itWeb3('Evm contract can receive wei from substrate account', async ({api, web3}) => { + const deployer = await createEthAccountWithBalance(api, web3); + const contract = await deployCollector(web3, deployer); + const alice = privateKey('//Alice'); + + // Transaction fee/value will be payed from subToEth(sender) evm balance, + // which is backed by evmToAddress(subToEth(sender)) substrate balance + await transferBalanceExpectSuccess(api, alice, evmToAddress(subToEth(alice.address)), '1000000000000'); + + { + const tx = api.tx.evm.call( + subToEth(alice.address), + contract.options.address, + contract.methods.giveMoney().encodeABI(), + '10000', + GAS_ARGS.gas, + GAS_ARGS.gasPrice, + null, + ); + const events = await submitTransactionAsync(alice, tx); + const result = getGenericResult(events); + expect(result.success).to.be.true; + } + + expect(await contract.methods.getCollected().call()).to.be.equal('10000'); + }); + + // We can't handle sending balance to backing storage of evm balance, because evmToAddress operation is irreversible + itWeb3('Wei sent directly to backing storage of evm contract balance is unaccounted', async({api, web3}) => { + const deployer = await createEthAccountWithBalance(api, web3); + const contract = await deployCollector(web3, deployer); + const alice = privateKey('//Alice'); + + await transferBalanceExpectSuccess(api, alice, evmToAddress(contract.options.address), '10000'); + + expect(await contract.methods.getUnaccounted().call()).to.be.equal('10000'); + }); + + itWeb3('Balance can be retrieved from evm contract', async({api, web3}) => { + const FEE_BALANCE = 10n ** 18n; + const CONTRACT_BALANCE = 10n ** 14n; + + const deployer = await createEthAccountWithBalance(api, web3); + const contract = await deployCollector(web3, deployer); + const alice = privateKey('//Alice'); + + await web3.eth.sendTransaction({from: deployer, to: contract.options.address, value: CONTRACT_BALANCE.toString(), ...GAS_ARGS}); + await waitNewBlocks(api, 1); + + const receiver = privateKey(`//Receiver${Date.now()}`); + + // First receive balance on eth balance of bob + { + const ethReceiver = subToEth(receiver.address); + expect(await web3.eth.getBalance(ethReceiver)).to.be.equal('0'); + await contract.methods.withdraw(ethReceiver).send({from: deployer}); + expect(await web3.eth.getBalance(ethReceiver)).to.be.equal(CONTRACT_BALANCE.toString()); + } + + // Some balance is required to pay fee for evm.withdraw call + await transferBalanceExpectSuccess(api, alice, receiver.address, FEE_BALANCE.toString()); + + // Withdraw balance from eth to substrate + { + const initialReceiverBalance = await getBalanceSingle(api, receiver.address); + const tx = api.tx.evm.withdraw( + subToEth(receiver.address), + CONTRACT_BALANCE.toString(), + ); + const events = await submitTransactionAsync(receiver, tx); + const result = getGenericResult(events); + expect(result.success).to.be.true; + const finalReceiverBalance = await getBalanceSingle(api, receiver.address); + + expect(finalReceiverBalance > initialReceiverBalance).to.be.true; + } + }); +}); \ No newline at end of file --- a/tests/src/eth/util/helpers.ts +++ b/tests/src/eth/util/helpers.ts @@ -17,6 +17,8 @@ import config from '../../config'; import privateKey from '../../substrate/privateKey'; import contractHelpersAbi from './contractHelpersAbi.json'; +import getBalance from '../../substrate/get-balance'; +import waitNewBlocks from '../../substrate/wait-new-blocks'; export const GAS_ARGS = { gas: 0x1000000, gasPrice: '0x01' }; @@ -37,12 +39,12 @@ } } -type Web3HttpMarker = {web3Http: true}; - -export async function usingWeb3Http(cb: (web3: Web3 & Web3HttpMarker) => Promise | T): Promise { +/** + * @deprecated Web3 update solved issue with deployment over ws provider + */ +export async function usingWeb3Http(cb: (web3: Web3) => Promise | T): Promise { const provider = new Web3.providers.HttpProvider(config.frontierUrl); - const web3: Web3 & Web3HttpMarker = new Web3(provider) as any; - web3.web3Http = true; + const web3: Web3 = new Web3(provider); return await cb(web3); } @@ -178,7 +180,7 @@ }; } -export async function deployFlipper(web3: Web3 & Web3HttpMarker, deployer: string) { +export async function deployFlipper(web3: Web3, deployer: string) { const compiled = compileContract('Flipper', ` contract Flipper { bool value = false; @@ -200,16 +202,27 @@ return flipper; } -export async function deployCollector(web3: Web3 & Web3HttpMarker, deployer: string) { +export async function deployCollector(web3: Web3, deployer: string) { const compiled = compileContract('Collector', ` contract Collector { uint256 collected; + fallback() external payable { + giveMoney(); + } function giveMoney() public payable { collected += msg.value; } function getCollected() public view returns (uint256) { return collected; } + function getUnaccounted() public view returns (uint256) { + return address(this).balance - collected; + } + + function withdraw(address payable target) public { + target.transfer(collected); + collected = 0; + } } `); const Collector = new web3.eth.Contract(compiled.abi, undefined, { @@ -238,4 +251,22 @@ ); const events = await submitTransactionAsync(from, tx); expect(events.find(({ event: {section, method}})=>section === 'evm' && method === 'Executed')).to.be.not.undefined; +} + +export async function ethBalanceViaSub(api: ApiPromise, address: string): Promise { + return (await getBalance(api, [evmToAddress(address)]))[0]; +} + +export async function recordEthFee(api: ApiPromise, user: string, call: () => Promise): Promise { + const before = await ethBalanceViaSub(api, user); + + await call(); + await waitNewBlocks(api, 1); + + const after = await ethBalanceViaSub(api, user); + + // Can't use .to.be.less, because chai doesn't supports bigint + expect(after < before).to.be.true; + + return before - after; } \ No newline at end of file --- a/tests/src/substrate/get-balance.ts +++ b/tests/src/substrate/get-balance.ts @@ -6,9 +6,24 @@ import { ApiPromise } from '@polkadot/api'; import {AccountInfo} from '@polkadot/types/interfaces/system'; import promisifySubstrate from './promisify-substrate'; +import { IKeyringPair } from '@polkadot/types/types'; +import { submitTransactionAsync } from './substrate-api'; +import { getGenericResult } from '../util/helpers'; +import { expect } from 'chai'; export default async function getBalance(api: ApiPromise, accounts: string[]): Promise> { const balance = promisifySubstrate(api, (acc: string[]) => api.query.system.account.multi(acc)); const responce = await balance(accounts) as unknown as AccountInfo[]; return responce.map((r) => r.data.free.toBigInt().valueOf()); } + +export async function getBalanceSingle(api: ApiPromise, account: string): Promise { + return (await getBalance(api, [account]))[0]; +} + +export async function transferBalanceExpectSuccess(api: ApiPromise, from: IKeyringPair, to: string, amount: bigint | string) { + const tx = api.tx.balances.transfer(to, amount); + const events = await submitTransactionAsync(from, tx); + const result = getGenericResult(events); + expect(result.success).to.be.true; +} \ No newline at end of file --- a/tests/src/util/helpers.ts +++ b/tests/src/util/helpers.ts @@ -53,6 +53,11 @@ export const U128_MAX = (1n << 128n) - 1n; +const MICROUNIQUE = 1_000_000_000n; +const MILLIUNIQUE = 1_000n * MICROUNIQUE; +const CENTIUNIQUE = 10n * MILLIUNIQUE; +export const UNIQUE = 100n * CENTIUNIQUE; + type GenericResult = { success: boolean, }; --- a/tests/yarn.lock +++ b/tests/yarn.lock @@ -2,10 +2,10 @@ # yarn lockfile v1 -"@babel/cli@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/cli/-/cli-7.14.5.tgz#9551b194f02360729de6060785bbdcce52c69f0a" - integrity sha512-poegjhRvXHWO0EAsnYajwYZuqcz7gyfxwfaecUESxDujrqOivf3zrjFbub8IJkrqEaz3fvJWh001EzxBub54fg== +"@babel/cli@^7.14.8": + version "7.14.8" + resolved "https://registry.yarnpkg.com/@babel/cli/-/cli-7.14.8.tgz#fac73c0e2328a8af9fd3560c06b096bfa3730933" + integrity sha512-lcy6Lymft9Rpfqmrqdd4oTDdUx9ZwaAhAfywVrHG4771Pa6PPT0danJ1kDHBXYqh4HHSmIdA+nlmfxfxSDPtBg== dependencies: commander "^4.0.1" convert-source-map "^1.1.0" @@ -42,7 +42,12 @@ resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.14.7.tgz#7b047d7a3a89a67d2258dc61f604f098f1bc7e08" integrity sha512-nS6dZaISCXJ3+518CWiBfEr//gHyMO02uDxBkXTKZDN5POruCnOZ1N4YBRZDCabwF8nZMWBpRxIicmXtBs+fvw== -"@babel/core@^7.1.0", "@babel/core@^7.14.6", "@babel/core@^7.7.2", "@babel/core@^7.7.5": +"@babel/compat-data@^7.15.0": + version "7.15.0" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.15.0.tgz#2dbaf8b85334796cafbb0f5793a90a2fc010b176" + integrity sha512-0NqAC1IJE0S0+lL1SWFMxMkz1pKCNCjI4tr2Zx4LJSXxCLAdr6KyArnY+sno5m3yH9g737ygOyPABDsnXkpxiA== + +"@babel/core@^7.1.0", "@babel/core@^7.7.2", "@babel/core@^7.7.5": version "7.14.6" resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.14.6.tgz#e0814ec1a950032ff16c13a2721de39a8416fcab" integrity sha512-gJnOEWSqTk96qG5BoIrl5bVtc23DCycmIePPYnamY9RboYdI4nFy5vAQMSl81O5K/W0sLDWfGysnOECC+KUUCA== @@ -63,6 +68,27 @@ semver "^6.3.0" source-map "^0.5.0" +"@babel/core@^7.15.0": + version "7.15.0" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.15.0.tgz#749e57c68778b73ad8082775561f67f5196aafa8" + integrity sha512-tXtmTminrze5HEUPn/a0JtOzzfp0nk+UEXQ/tqIJo3WDGypl/2OFQEMll/zSFU8f/lfmfLXvTaORHF3cfXIQMw== + dependencies: + "@babel/code-frame" "^7.14.5" + "@babel/generator" "^7.15.0" + "@babel/helper-compilation-targets" "^7.15.0" + "@babel/helper-module-transforms" "^7.15.0" + "@babel/helpers" "^7.14.8" + "@babel/parser" "^7.15.0" + "@babel/template" "^7.14.5" + "@babel/traverse" "^7.15.0" + "@babel/types" "^7.15.0" + convert-source-map "^1.7.0" + debug "^4.1.0" + gensync "^1.0.0-beta.2" + json5 "^2.1.2" + semver "^6.3.0" + source-map "^0.5.0" + "@babel/generator@^7.14.5", "@babel/generator@^7.7.2": version "7.14.5" resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.14.5.tgz#848d7b9f031caca9d0cd0af01b063f226f52d785" @@ -72,6 +98,15 @@ jsesc "^2.5.1" source-map "^0.5.0" +"@babel/generator@^7.15.0": + version "7.15.0" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.15.0.tgz#a7d0c172e0d814974bad5aa77ace543b97917f15" + integrity sha512-eKl4XdMrbpYvuB505KTta4AV9g+wWzmVBW69tX0H2NwKVKd2YJbKgyK6M8j/rgLbmHOYJn6rUklV677nOyJrEQ== + dependencies: + "@babel/types" "^7.15.0" + jsesc "^2.5.1" + source-map "^0.5.0" + "@babel/helper-annotate-as-pure@^7.0.0", "@babel/helper-annotate-as-pure@^7.14.5": version "7.14.5" resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.14.5.tgz#7bf478ec3b71726d56a8ca5775b046fc29879e61" @@ -97,7 +132,17 @@ browserslist "^4.16.6" semver "^6.3.0" -"@babel/helper-create-class-features-plugin@^7.14.5", "@babel/helper-create-class-features-plugin@^7.14.6": +"@babel/helper-compilation-targets@^7.15.0": + version "7.15.0" + resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.15.0.tgz#973df8cbd025515f3ff25db0c05efc704fa79818" + integrity sha512-h+/9t0ncd4jfZ8wsdAsoIxSa61qhBYlycXiHWqJaQBCXAhDCMbPRSMTGnZIkkmt1u4ag+UQmuqcILwqKzZ4N2A== + dependencies: + "@babel/compat-data" "^7.15.0" + "@babel/helper-validator-option" "^7.14.5" + browserslist "^4.16.6" + semver "^6.3.0" + +"@babel/helper-create-class-features-plugin@^7.14.5": version "7.14.6" resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.14.6.tgz#f114469b6c06f8b5c59c6c4e74621f5085362542" integrity sha512-Z6gsfGofTxH/+LQXqYEK45kxmcensbzmk/oi8DmaQytlQCgqNZt9XQF8iqlI/SeXWVjaMNxvYvzaYw+kh42mDg== @@ -109,6 +154,18 @@ "@babel/helper-replace-supers" "^7.14.5" "@babel/helper-split-export-declaration" "^7.14.5" +"@babel/helper-create-class-features-plugin@^7.15.0": + version "7.15.0" + resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.15.0.tgz#c9a137a4d137b2d0e2c649acf536d7ba1a76c0f7" + integrity sha512-MdmDXgvTIi4heDVX/e9EFfeGpugqm9fobBVg/iioE8kueXrOHdRDe36FAY7SnE9xXLVeYCoJR/gdrBEIHRC83Q== + dependencies: + "@babel/helper-annotate-as-pure" "^7.14.5" + "@babel/helper-function-name" "^7.14.5" + "@babel/helper-member-expression-to-functions" "^7.15.0" + "@babel/helper-optimise-call-expression" "^7.14.5" + "@babel/helper-replace-supers" "^7.15.0" + "@babel/helper-split-export-declaration" "^7.14.5" + "@babel/helper-create-regexp-features-plugin@^7.14.5": version "7.14.5" resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.14.5.tgz#c7d5ac5e9cf621c26057722fb7a8a4c5889358c4" @@ -168,6 +225,13 @@ dependencies: "@babel/types" "^7.14.5" +"@babel/helper-member-expression-to-functions@^7.15.0": + version "7.15.0" + resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.15.0.tgz#0ddaf5299c8179f27f37327936553e9bba60990b" + integrity sha512-Jq8H8U2kYiafuj2xMTPQwkTBnEEdGKpT35lJEQsRRjnG0LW3neucsaMWLgKcwu3OHKNeYugfw+Z20BXBSEs2Lg== + dependencies: + "@babel/types" "^7.15.0" + "@babel/helper-module-imports@^7.0.0", "@babel/helper-module-imports@^7.12.13", "@babel/helper-module-imports@^7.14.5": version "7.14.5" resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.14.5.tgz#6d1a44df6a38c957aa7c312da076429f11b422f3" @@ -189,6 +253,20 @@ "@babel/traverse" "^7.14.5" "@babel/types" "^7.14.5" +"@babel/helper-module-transforms@^7.15.0": + version "7.15.0" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.15.0.tgz#679275581ea056373eddbe360e1419ef23783b08" + integrity sha512-RkGiW5Rer7fpXv9m1B3iHIFDZdItnO2/BLfWVW/9q7+KqQSDY5kUfQEbzdXM1MVhJGcugKV7kRrNVzNxmk7NBg== + dependencies: + "@babel/helper-module-imports" "^7.14.5" + "@babel/helper-replace-supers" "^7.15.0" + "@babel/helper-simple-access" "^7.14.8" + "@babel/helper-split-export-declaration" "^7.14.5" + "@babel/helper-validator-identifier" "^7.14.9" + "@babel/template" "^7.14.5" + "@babel/traverse" "^7.15.0" + "@babel/types" "^7.15.0" + "@babel/helper-optimise-call-expression@^7.14.5": version "7.14.5" resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.14.5.tgz#f27395a8619e0665b3f0364cddb41c25d71b499c" @@ -220,6 +298,16 @@ "@babel/traverse" "^7.14.5" "@babel/types" "^7.14.5" +"@babel/helper-replace-supers@^7.15.0": + version "7.15.0" + resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.15.0.tgz#ace07708f5bf746bf2e6ba99572cce79b5d4e7f4" + integrity sha512-6O+eWrhx+HEra/uJnifCwhwMd6Bp5+ZfZeJwbqUTuqkhIT6YcRhiZCOOFChRypOIe0cV46kFrRBlm+t5vHCEaA== + dependencies: + "@babel/helper-member-expression-to-functions" "^7.15.0" + "@babel/helper-optimise-call-expression" "^7.14.5" + "@babel/traverse" "^7.15.0" + "@babel/types" "^7.15.0" + "@babel/helper-simple-access@^7.14.5": version "7.14.5" resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.14.5.tgz#66ea85cf53ba0b4e588ba77fc813f53abcaa41c4" @@ -227,6 +315,13 @@ dependencies: "@babel/types" "^7.14.5" +"@babel/helper-simple-access@^7.14.8": + version "7.14.8" + resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.14.8.tgz#82e1fec0644a7e775c74d305f212c39f8fe73924" + integrity sha512-TrFN4RHh9gnWEU+s7JloIho2T76GPwRHhdzOWLqTrMnlas8T9O7ec+oEDNsRXndOmru9ymH9DFrEOxpzPoSbdg== + dependencies: + "@babel/types" "^7.14.8" + "@babel/helper-skip-transparent-expression-wrappers@^7.14.5": version "7.14.5" resolved "https://registry.yarnpkg.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.14.5.tgz#96f486ac050ca9f44b009fbe5b7d394cab3a0ee4" @@ -246,6 +341,11 @@ resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.5.tgz#d0f0e277c512e0c938277faa85a3968c9a44c0e8" integrity sha512-5lsetuxCLilmVGyiLEfoHBRX8UCFD+1m2x3Rj97WrW3V7H3u4RWRXA4evMjImCsin2J2YT0QaVDGf+z8ondbAg== +"@babel/helper-validator-identifier@^7.14.9": + version "7.14.9" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.9.tgz#6654d171b2024f6d8ee151bf2509699919131d48" + integrity sha512-pQYxPY0UP6IHISRitNe8bsijHex4TWZXi2HwKVsjPiltzlhse2znVcm9Ace510VT1kxIHjGJCZZQBX2gJDbo0g== + "@babel/helper-validator-option@^7.14.5": version "7.14.5" resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.14.5.tgz#6e72a1fff18d5dfcb878e1e62f1a021c4b72d5a3" @@ -270,6 +370,15 @@ "@babel/traverse" "^7.14.5" "@babel/types" "^7.14.5" +"@babel/helpers@^7.14.8": + version "7.15.3" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.15.3.tgz#c96838b752b95dcd525b4e741ed40bb1dc2a1357" + integrity sha512-HwJiz52XaS96lX+28Tnbu31VeFSQJGOeKHJeaEPQlTl7PnlhFElWPj8tUXtqFIzeN86XxXoBr+WFAyK2PPVz6g== + dependencies: + "@babel/template" "^7.14.5" + "@babel/traverse" "^7.15.0" + "@babel/types" "^7.15.0" + "@babel/highlight@^7.10.4", "@babel/highlight@^7.14.5": version "7.14.5" resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.14.5.tgz#6861a52f03966405001f6aa534a01a24d99e8cd9" @@ -284,6 +393,11 @@ resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.14.6.tgz#d85cc68ca3cac84eae384c06f032921f5227f4b2" integrity sha512-oG0ej7efjEXxb4UgE+klVx+3j4MVo+A2vCzm7OUN4CLo6WhQ+vSOD2yJ8m7B+DghObxtLxt3EfgMWpq+AsWehQ== +"@babel/parser@^7.15.0": + version "7.15.3" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.15.3.tgz#3416d9bea748052cfcb63dbcc27368105b1ed862" + integrity sha512-O0L6v/HvqbdJawj0iBEfVQMc3/6WP+AeOsovsIgBFyJaG+W2w7eqvZB7puddATmWuARlm1SX7DwxJ/JJUnDpEA== + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@^7.14.5": version "7.14.5" resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.14.5.tgz#4b467302e1548ed3b1be43beae2cc9cf45e0bb7e" @@ -293,10 +407,10 @@ "@babel/helper-skip-transparent-expression-wrappers" "^7.14.5" "@babel/plugin-proposal-optional-chaining" "^7.14.5" -"@babel/plugin-proposal-async-generator-functions@^7.14.7": - version "7.14.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.14.7.tgz#784a48c3d8ed073f65adcf30b57bcbf6c8119ace" - integrity sha512-RK8Wj7lXLY3bqei69/cc25gwS5puEc3dknoFPFbqfy3XxYQBQFvu4ioWpafMBAB+L9NyptQK4nMOa5Xz16og8Q== +"@babel/plugin-proposal-async-generator-functions@^7.14.9": + version "7.14.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.14.9.tgz#7028dc4fa21dc199bbacf98b39bab1267d0eaf9a" + integrity sha512-d1lnh+ZnKrFKwtTYdw320+sQWCTwgkB9fmUhNXRADA4akR6wLjaruSGnIEUjpt9HCOwTr4ynFTKu19b7rFRpmw== dependencies: "@babel/helper-plugin-utils" "^7.14.5" "@babel/helper-remap-async-to-generator" "^7.14.5" @@ -577,10 +691,10 @@ dependencies: "@babel/helper-plugin-utils" "^7.14.5" -"@babel/plugin-transform-classes@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.14.5.tgz#0e98e82097b38550b03b483f9b51a78de0acb2cf" - integrity sha512-J4VxKAMykM06K/64z9rwiL6xnBHgB1+FVspqvlgCdwD1KUbQNfszeKVVOMh59w3sztHYIZDgnhOC4WbdEfHFDA== +"@babel/plugin-transform-classes@^7.14.9": + version "7.14.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.14.9.tgz#2a391ffb1e5292710b00f2e2c210e1435e7d449f" + integrity sha512-NfZpTcxU3foGWbl4wxmZ35mTsYJy8oQocbeIMoDAGGFarAmSQlL+LWMkDx/tj6pNotpbX3rltIA4dprgAPOq5A== dependencies: "@babel/helper-annotate-as-pure" "^7.14.5" "@babel/helper-function-name" "^7.14.5" @@ -665,14 +779,14 @@ "@babel/helper-plugin-utils" "^7.14.5" babel-plugin-dynamic-import-node "^2.3.3" -"@babel/plugin-transform-modules-commonjs@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.14.5.tgz#7aaee0ea98283de94da98b28f8c35701429dad97" - integrity sha512-en8GfBtgnydoao2PS+87mKyw62k02k7kJ9ltbKe0fXTHrQmG6QZZflYuGI1VVG7sVpx4E1n7KBpNlPb8m78J+A== +"@babel/plugin-transform-modules-commonjs@^7.15.0": + version "7.15.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.15.0.tgz#3305896e5835f953b5cdb363acd9e8c2219a5281" + integrity sha512-3H/R9s8cXcOGE8kgMlmjYYC9nqr5ELiPkJn4q0mypBrjhYQoc+5/Maq69vV4xRPWnkzZuwJPf5rArxpB/35Cig== dependencies: - "@babel/helper-module-transforms" "^7.14.5" + "@babel/helper-module-transforms" "^7.15.0" "@babel/helper-plugin-utils" "^7.14.5" - "@babel/helper-simple-access" "^7.14.5" + "@babel/helper-simple-access" "^7.14.8" babel-plugin-dynamic-import-node "^2.3.3" "@babel/plugin-transform-modules-systemjs@^7.14.5": @@ -694,10 +808,10 @@ "@babel/helper-module-transforms" "^7.14.5" "@babel/helper-plugin-utils" "^7.14.5" -"@babel/plugin-transform-named-capturing-groups-regex@^7.14.7": - version "7.14.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.14.7.tgz#60c06892acf9df231e256c24464bfecb0908fd4e" - integrity sha512-DTNOTaS7TkW97xsDMrp7nycUVh6sn/eq22VaxWfEdzuEbRsiaOU0pqU7DlyUGHVsbQbSghvjKRpEl+nUCKGQSg== +"@babel/plugin-transform-named-capturing-groups-regex@^7.14.9": + version "7.14.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.14.9.tgz#c68f5c5d12d2ebaba3762e57c2c4f6347a46e7b2" + integrity sha512-l666wCVYO75mlAtGFfyFwnWmIXQm3kSH0C3IRnJqWcZbWkoihyAdDhFm2ZWaxWTqvBvhVFfJjMRQ0ez4oN1yYA== dependencies: "@babel/helper-create-regexp-features-plugin" "^7.14.5" @@ -777,10 +891,10 @@ dependencies: "@babel/helper-plugin-utils" "^7.14.5" -"@babel/plugin-transform-runtime@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.14.5.tgz#30491dad49c6059f8f8fa5ee8896a0089e987523" - integrity sha512-fPMBhh1AV8ZyneiCIA+wYYUH1arzlXR1UMcApjvchDhfKxhy2r2lReJv8uHEyihi4IFIGlr1Pdx7S5fkESDQsg== +"@babel/plugin-transform-runtime@^7.15.0": + version "7.15.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.15.0.tgz#d3aa650d11678ca76ce294071fda53d7804183b3" + integrity sha512-sfHYkLGjhzWTq6xsuQ01oEsUYjkHRux9fW1iUA68dC7Qd8BS1Unq4aZ8itmQp95zUzIcyR2EbNMTzAicFj+guw== dependencies: "@babel/helper-module-imports" "^7.14.5" "@babel/helper-plugin-utils" "^7.14.5" @@ -825,12 +939,12 @@ dependencies: "@babel/helper-plugin-utils" "^7.14.5" -"@babel/plugin-transform-typescript@^7.14.5": - version "7.14.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.14.6.tgz#6e9c2d98da2507ebe0a883b100cde3c7279df36c" - integrity sha512-XlTdBq7Awr4FYIzqhmYY80WN0V0azF74DMPyFqVHBvf81ZUgc4X7ZOpx6O8eLDK6iM5cCQzeyJw0ynTaefixRA== +"@babel/plugin-transform-typescript@^7.15.0": + version "7.15.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.15.0.tgz#553f230b9d5385018716586fc48db10dd228eb7e" + integrity sha512-WIIEazmngMEEHDaPTx0IZY48SaAmjVWe3TRSX7cmJXn0bEv9midFzAjxiruOWYIVf5iQ10vFx7ASDpgEO08L5w== dependencies: - "@babel/helper-create-class-features-plugin" "^7.14.6" + "@babel/helper-create-class-features-plugin" "^7.15.0" "@babel/helper-plugin-utils" "^7.14.5" "@babel/plugin-syntax-typescript" "^7.14.5" @@ -849,17 +963,17 @@ "@babel/helper-create-regexp-features-plugin" "^7.14.5" "@babel/helper-plugin-utils" "^7.14.5" -"@babel/preset-env@^7.14.7": - version "7.14.7" - resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.14.7.tgz#5c70b22d4c2d893b03d8c886a5c17422502b932a" - integrity sha512-itOGqCKLsSUl0Y+1nSfhbuuOlTs0MJk2Iv7iSH+XT/mR8U1zRLO7NjWlYXB47yhK4J/7j+HYty/EhFZDYKa/VA== +"@babel/preset-env@^7.15.0": + version "7.15.0" + resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.15.0.tgz#e2165bf16594c9c05e52517a194bf6187d6fe464" + integrity sha512-FhEpCNFCcWW3iZLg0L2NPE9UerdtsCR6ZcsGHUX6Om6kbCQeL5QZDqFDmeNHC6/fy6UH3jEge7K4qG5uC9In0Q== dependencies: - "@babel/compat-data" "^7.14.7" - "@babel/helper-compilation-targets" "^7.14.5" + "@babel/compat-data" "^7.15.0" + "@babel/helper-compilation-targets" "^7.15.0" "@babel/helper-plugin-utils" "^7.14.5" "@babel/helper-validator-option" "^7.14.5" "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining" "^7.14.5" - "@babel/plugin-proposal-async-generator-functions" "^7.14.7" + "@babel/plugin-proposal-async-generator-functions" "^7.14.9" "@babel/plugin-proposal-class-properties" "^7.14.5" "@babel/plugin-proposal-class-static-block" "^7.14.5" "@babel/plugin-proposal-dynamic-import" "^7.14.5" @@ -892,7 +1006,7 @@ "@babel/plugin-transform-async-to-generator" "^7.14.5" "@babel/plugin-transform-block-scoped-functions" "^7.14.5" "@babel/plugin-transform-block-scoping" "^7.14.5" - "@babel/plugin-transform-classes" "^7.14.5" + "@babel/plugin-transform-classes" "^7.14.9" "@babel/plugin-transform-computed-properties" "^7.14.5" "@babel/plugin-transform-destructuring" "^7.14.7" "@babel/plugin-transform-dotall-regex" "^7.14.5" @@ -903,10 +1017,10 @@ "@babel/plugin-transform-literals" "^7.14.5" "@babel/plugin-transform-member-expression-literals" "^7.14.5" "@babel/plugin-transform-modules-amd" "^7.14.5" - "@babel/plugin-transform-modules-commonjs" "^7.14.5" + "@babel/plugin-transform-modules-commonjs" "^7.15.0" "@babel/plugin-transform-modules-systemjs" "^7.14.5" "@babel/plugin-transform-modules-umd" "^7.14.5" - "@babel/plugin-transform-named-capturing-groups-regex" "^7.14.7" + "@babel/plugin-transform-named-capturing-groups-regex" "^7.14.9" "@babel/plugin-transform-new-target" "^7.14.5" "@babel/plugin-transform-object-super" "^7.14.5" "@babel/plugin-transform-parameters" "^7.14.5" @@ -921,11 +1035,11 @@ "@babel/plugin-transform-unicode-escapes" "^7.14.5" "@babel/plugin-transform-unicode-regex" "^7.14.5" "@babel/preset-modules" "^0.1.4" - "@babel/types" "^7.14.5" + "@babel/types" "^7.15.0" babel-plugin-polyfill-corejs2 "^0.2.2" babel-plugin-polyfill-corejs3 "^0.2.2" babel-plugin-polyfill-regenerator "^0.2.2" - core-js-compat "^3.15.0" + core-js-compat "^3.16.0" semver "^6.3.0" "@babel/preset-modules@^0.1.4": @@ -951,19 +1065,19 @@ "@babel/plugin-transform-react-jsx-development" "^7.14.5" "@babel/plugin-transform-react-pure-annotations" "^7.14.5" -"@babel/preset-typescript@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/preset-typescript/-/preset-typescript-7.14.5.tgz#aa98de119cf9852b79511f19e7f44a2d379bcce0" - integrity sha512-u4zO6CdbRKbS9TypMqrlGH7sd2TAJppZwn3c/ZRLeO/wGsbddxgbPDUZVNrie3JWYLQ9vpineKlsrWFvO6Pwkw== +"@babel/preset-typescript@^7.15.0": + version "7.15.0" + resolved "https://registry.yarnpkg.com/@babel/preset-typescript/-/preset-typescript-7.15.0.tgz#e8fca638a1a0f64f14e1119f7fe4500277840945" + integrity sha512-lt0Y/8V3y06Wq/8H/u0WakrqciZ7Fz7mwPDHWUJAXlABL5hiUG42BNlRXiELNjeWjO5rWmnNKlx+yzJvxezHow== dependencies: "@babel/helper-plugin-utils" "^7.14.5" "@babel/helper-validator-option" "^7.14.5" - "@babel/plugin-transform-typescript" "^7.14.5" + "@babel/plugin-transform-typescript" "^7.15.0" -"@babel/register@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/register/-/register-7.14.5.tgz#d0eac615065d9c2f1995842f85d6e56c345f3233" - integrity sha512-TjJpGz/aDjFGWsItRBQMOFTrmTI9tr79CHOK+KIvLeCkbxuOAk2M5QHjvruIMGoo9OuccMh5euplPzc5FjAKGg== +"@babel/register@^7.15.3": + version "7.15.3" + resolved "https://registry.yarnpkg.com/@babel/register/-/register-7.15.3.tgz#6b40a549e06ec06c885b2ec42c3dd711f55fe752" + integrity sha512-mj4IY1ZJkorClxKTImccn4T81+UKTo4Ux0+OFSV9hME1ooqS9UV+pJ6BjD0qXPK4T3XW/KNa79XByjeEMZz+fw== dependencies: clone-deep "^4.0.1" find-cache-dir "^2.0.0" @@ -978,6 +1092,13 @@ dependencies: regenerator-runtime "^0.13.4" +"@babel/runtime@^7.15.3": + version "7.15.3" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.15.3.tgz#2e1c2880ca118e5b2f9988322bd8a7656a32502b" + integrity sha512-OvwMLqNXkCXSz1kSm58sEsNuhqOx/fKpnUnKnFB5v8uDda5bLNEHNgKPvhDN6IU0LDcnHQ90LlJ0Q6jnyBSIBA== + dependencies: + regenerator-runtime "^0.13.4" + "@babel/template@^7.14.5", "@babel/template@^7.3.3": version "7.14.5" resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.14.5.tgz#a9bc9d8b33354ff6e55a9c60d1109200a68974f4" @@ -1002,6 +1123,21 @@ debug "^4.1.0" globals "^11.1.0" +"@babel/traverse@^7.15.0": + version "7.15.0" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.15.0.tgz#4cca838fd1b2a03283c1f38e141f639d60b3fc98" + integrity sha512-392d8BN0C9eVxVWd8H6x9WfipgVH5IaIoLp23334Sc1vbKKWINnvwRpb4us0xtPaCumlwbTtIYNA0Dv/32sVFw== + dependencies: + "@babel/code-frame" "^7.14.5" + "@babel/generator" "^7.15.0" + "@babel/helper-function-name" "^7.14.5" + "@babel/helper-hoist-variables" "^7.14.5" + "@babel/helper-split-export-declaration" "^7.14.5" + "@babel/parser" "^7.15.0" + "@babel/types" "^7.15.0" + debug "^4.1.0" + globals "^11.1.0" + "@babel/types@^7.0.0", "@babel/types@^7.14.5", "@babel/types@^7.3.0", "@babel/types@^7.3.3", "@babel/types@^7.4.4": version "7.14.5" resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.14.5.tgz#3bb997ba829a2104cedb20689c4a5b8121d383ff" @@ -1010,26 +1146,19 @@ "@babel/helper-validator-identifier" "^7.14.5" to-fast-properties "^2.0.0" +"@babel/types@^7.14.8", "@babel/types@^7.15.0": + version "7.15.0" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.15.0.tgz#61af11f2286c4e9c69ca8deb5f4375a73c72dcbd" + integrity sha512-OBvfqnllOIdX4ojTHpwZbpvz4j3EWyjkZEdmjH0/cgsd6QOdSgU8rLSk6ard/pcW7rlmjdVSX/AWOaORR1uNOQ== + dependencies: + "@babel/helper-validator-identifier" "^7.14.9" + to-fast-properties "^2.0.0" + "@bcoe/v8-coverage@^0.2.3": version "0.2.3" resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== -"@eslint/eslintrc@^0.4.2": - version "0.4.2" - resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-0.4.2.tgz#f63d0ef06f5c0c57d76c4ab5f63d3835c51b0179" - integrity sha512-8nmGq/4ycLpIwzvhI4tNDmQztZ8sp+hI7cyG8i1nQDhkAbRzHpXPidRAHlNvCZQpJTKw5ItIpMw9RSToGF00mg== - dependencies: - ajv "^6.12.4" - debug "^4.1.1" - espree "^7.3.0" - globals "^13.9.0" - ignore "^4.0.6" - import-fresh "^3.2.1" - js-yaml "^3.13.1" - minimatch "^3.0.4" - strip-json-comments "^3.1.1" - "@eslint/eslintrc@^0.4.3": version "0.4.3" resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-0.4.3.tgz#9e42981ef035beb3dd49add17acb96e8ff6f394c" @@ -1251,94 +1380,94 @@ resolved "https://registry.yarnpkg.com/@istanbuljs/schema/-/schema-0.1.3.tgz#e45e384e4b8ec16bce2fd903af78450f6bf7ec98" integrity sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA== -"@jest/console@^27.0.2": - version "27.0.2" - resolved "https://registry.yarnpkg.com/@jest/console/-/console-27.0.2.tgz#b8eeff8f21ac51d224c851e1729d2630c18631e6" - integrity sha512-/zYigssuHLImGeMAACkjI4VLAiiJznHgAl3xnFT19iWyct2LhrH3KXOjHRmxBGTkiPLZKKAJAgaPpiU9EZ9K+w== +"@jest/console@^27.0.6": + version "27.0.6" + resolved "https://registry.yarnpkg.com/@jest/console/-/console-27.0.6.tgz#3eb72ea80897495c3d73dd97aab7f26770e2260f" + integrity sha512-fMlIBocSHPZ3JxgWiDNW/KPj6s+YRd0hicb33IrmelCcjXo/pXPwvuiKFmZz+XuqI/1u7nbUK10zSsWL/1aegg== dependencies: - "@jest/types" "^27.0.2" + "@jest/types" "^27.0.6" "@types/node" "*" chalk "^4.0.0" - jest-message-util "^27.0.2" - jest-util "^27.0.2" + jest-message-util "^27.0.6" + jest-util "^27.0.6" slash "^3.0.0" -"@jest/core@^27.0.5": - version "27.0.5" - resolved "https://registry.yarnpkg.com/@jest/core/-/core-27.0.5.tgz#59e9e69e7374d65dbb22e3fc1bd52e80991eae72" - integrity sha512-g73//jF0VwsOIrWUC9Cqg03lU3QoAMFxVjsm6n6yNmwZcQPN/o8w+gLWODw5VfKNFZT38otXHWxc6b8eGDUpEA== +"@jest/core@^27.0.6": + version "27.0.6" + resolved "https://registry.yarnpkg.com/@jest/core/-/core-27.0.6.tgz#c5f642727a0b3bf0f37c4b46c675372d0978d4a1" + integrity sha512-SsYBm3yhqOn5ZLJCtccaBcvD/ccTLCeuDv8U41WJH/V1MW5eKUkeMHT9U+Pw/v1m1AIWlnIW/eM2XzQr0rEmow== dependencies: - "@jest/console" "^27.0.2" - "@jest/reporters" "^27.0.5" - "@jest/test-result" "^27.0.2" - "@jest/transform" "^27.0.5" - "@jest/types" "^27.0.2" + "@jest/console" "^27.0.6" + "@jest/reporters" "^27.0.6" + "@jest/test-result" "^27.0.6" + "@jest/transform" "^27.0.6" + "@jest/types" "^27.0.6" "@types/node" "*" ansi-escapes "^4.2.1" chalk "^4.0.0" emittery "^0.8.1" exit "^0.1.2" graceful-fs "^4.2.4" - jest-changed-files "^27.0.2" - jest-config "^27.0.5" - jest-haste-map "^27.0.5" - jest-message-util "^27.0.2" - jest-regex-util "^27.0.1" - jest-resolve "^27.0.5" - jest-resolve-dependencies "^27.0.5" - jest-runner "^27.0.5" - jest-runtime "^27.0.5" - jest-snapshot "^27.0.5" - jest-util "^27.0.2" - jest-validate "^27.0.2" - jest-watcher "^27.0.2" + jest-changed-files "^27.0.6" + jest-config "^27.0.6" + jest-haste-map "^27.0.6" + jest-message-util "^27.0.6" + jest-regex-util "^27.0.6" + jest-resolve "^27.0.6" + jest-resolve-dependencies "^27.0.6" + jest-runner "^27.0.6" + jest-runtime "^27.0.6" + jest-snapshot "^27.0.6" + jest-util "^27.0.6" + jest-validate "^27.0.6" + jest-watcher "^27.0.6" micromatch "^4.0.4" p-each-series "^2.1.0" rimraf "^3.0.0" slash "^3.0.0" strip-ansi "^6.0.0" -"@jest/environment@^27.0.5": - version "27.0.5" - resolved "https://registry.yarnpkg.com/@jest/environment/-/environment-27.0.5.tgz#a294ad4acda2e250f789fb98dc667aad33d3adc9" - integrity sha512-IAkJPOT7bqn0GiX5LPio6/e1YpcmLbrd8O5EFYpAOZ6V+9xJDsXjdgN2vgv9WOKIs/uA1kf5WeD96HhlBYO+FA== +"@jest/environment@^27.0.6": + version "27.0.6" + resolved "https://registry.yarnpkg.com/@jest/environment/-/environment-27.0.6.tgz#ee293fe996db01d7d663b8108fa0e1ff436219d2" + integrity sha512-4XywtdhwZwCpPJ/qfAkqExRsERW+UaoSRStSHCCiQTUpoYdLukj+YJbQSFrZjhlUDRZeNiU9SFH0u7iNimdiIg== dependencies: - "@jest/fake-timers" "^27.0.5" - "@jest/types" "^27.0.2" + "@jest/fake-timers" "^27.0.6" + "@jest/types" "^27.0.6" "@types/node" "*" - jest-mock "^27.0.3" + jest-mock "^27.0.6" -"@jest/fake-timers@^27.0.5": - version "27.0.5" - resolved "https://registry.yarnpkg.com/@jest/fake-timers/-/fake-timers-27.0.5.tgz#304d5aedadf4c75cff3696995460b39d6c6e72f6" - integrity sha512-d6Tyf7iDoKqeUdwUKrOBV/GvEZRF67m7lpuWI0+SCD9D3aaejiOQZxAOxwH2EH/W18gnfYaBPLi0VeTGBHtQBg== +"@jest/fake-timers@^27.0.6": + version "27.0.6" + resolved "https://registry.yarnpkg.com/@jest/fake-timers/-/fake-timers-27.0.6.tgz#cbad52f3fe6abe30e7acb8cd5fa3466b9588e3df" + integrity sha512-sqd+xTWtZ94l3yWDKnRTdvTeZ+A/V7SSKrxsrOKSqdyddb9CeNRF8fbhAU0D7ZJBpTTW2nbp6MftmKJDZfW2LQ== dependencies: - "@jest/types" "^27.0.2" + "@jest/types" "^27.0.6" "@sinonjs/fake-timers" "^7.0.2" "@types/node" "*" - jest-message-util "^27.0.2" - jest-mock "^27.0.3" - jest-util "^27.0.2" + jest-message-util "^27.0.6" + jest-mock "^27.0.6" + jest-util "^27.0.6" -"@jest/globals@^27.0.5": - version "27.0.5" - resolved "https://registry.yarnpkg.com/@jest/globals/-/globals-27.0.5.tgz#f63b8bfa6ea3716f8df50f6a604b5c15b36ffd20" - integrity sha512-qqKyjDXUaZwDuccpbMMKCCMBftvrbXzigtIsikAH/9ca+kaae8InP2MDf+Y/PdCSMuAsSpHS6q6M25irBBUh+Q== +"@jest/globals@^27.0.6": + version "27.0.6" + resolved "https://registry.yarnpkg.com/@jest/globals/-/globals-27.0.6.tgz#48e3903f99a4650673d8657334d13c9caf0e8f82" + integrity sha512-DdTGCP606rh9bjkdQ7VvChV18iS7q0IMJVP1piwTWyWskol4iqcVwthZmoJEf7obE1nc34OpIyoVGPeqLC+ryw== dependencies: - "@jest/environment" "^27.0.5" - "@jest/types" "^27.0.2" - expect "^27.0.2" + "@jest/environment" "^27.0.6" + "@jest/types" "^27.0.6" + expect "^27.0.6" -"@jest/reporters@^27.0.5": - version "27.0.5" - resolved "https://registry.yarnpkg.com/@jest/reporters/-/reporters-27.0.5.tgz#cd730b77d9667b8ff700ad66d4edc293bb09716a" - integrity sha512-4uNg5+0eIfRafnpgu3jCZws3NNcFzhu5JdRd1mKQ4/53+vkIqwB6vfZ4gn5BdGqOaLtYhlOsPaL5ATkKzyBrJw== +"@jest/reporters@^27.0.6": + version "27.0.6" + resolved "https://registry.yarnpkg.com/@jest/reporters/-/reporters-27.0.6.tgz#91e7f2d98c002ad5df94d5b5167c1eb0b9fd5b00" + integrity sha512-TIkBt09Cb2gptji3yJXb3EE+eVltW6BjO7frO7NEfjI9vSIYoISi5R3aI3KpEDXlB1xwB+97NXIqz84qYeYsfA== dependencies: "@bcoe/v8-coverage" "^0.2.3" - "@jest/console" "^27.0.2" - "@jest/test-result" "^27.0.2" - "@jest/transform" "^27.0.5" - "@jest/types" "^27.0.2" + "@jest/console" "^27.0.6" + "@jest/test-result" "^27.0.6" + "@jest/transform" "^27.0.6" + "@jest/types" "^27.0.6" chalk "^4.0.0" collect-v8-coverage "^1.0.0" exit "^0.1.2" @@ -1349,70 +1478,70 @@ istanbul-lib-report "^3.0.0" istanbul-lib-source-maps "^4.0.0" istanbul-reports "^3.0.2" - jest-haste-map "^27.0.5" - jest-resolve "^27.0.5" - jest-util "^27.0.2" - jest-worker "^27.0.2" + jest-haste-map "^27.0.6" + jest-resolve "^27.0.6" + jest-util "^27.0.6" + jest-worker "^27.0.6" slash "^3.0.0" source-map "^0.6.0" string-length "^4.0.1" terminal-link "^2.0.0" v8-to-istanbul "^8.0.0" -"@jest/source-map@^27.0.1": - version "27.0.1" - resolved "https://registry.yarnpkg.com/@jest/source-map/-/source-map-27.0.1.tgz#2afbf73ddbaddcb920a8e62d0238a0a9e0a8d3e4" - integrity sha512-yMgkF0f+6WJtDMdDYNavmqvbHtiSpwRN2U/W+6uztgfqgkq/PXdKPqjBTUF1RD/feth4rH5N3NW0T5+wIuln1A== +"@jest/source-map@^27.0.6": + version "27.0.6" + resolved "https://registry.yarnpkg.com/@jest/source-map/-/source-map-27.0.6.tgz#be9e9b93565d49b0548b86e232092491fb60551f" + integrity sha512-Fek4mi5KQrqmlY07T23JRi0e7Z9bXTOOD86V/uS0EIW4PClvPDqZOyFlLpNJheS6QI0FNX1CgmPjtJ4EA/2M+g== dependencies: callsites "^3.0.0" graceful-fs "^4.2.4" source-map "^0.6.0" -"@jest/test-result@^27.0.2": - version "27.0.2" - resolved "https://registry.yarnpkg.com/@jest/test-result/-/test-result-27.0.2.tgz#0451049e32ceb609b636004ccc27c8fa22263f10" - integrity sha512-gcdWwL3yP5VaIadzwQtbZyZMgpmes8ryBAJp70tuxghiA8qL4imJyZex+i+USQH2H4jeLVVszhwntgdQ97fccA== +"@jest/test-result@^27.0.6": + version "27.0.6" + resolved "https://registry.yarnpkg.com/@jest/test-result/-/test-result-27.0.6.tgz#3fa42015a14e4fdede6acd042ce98c7f36627051" + integrity sha512-ja/pBOMTufjX4JLEauLxE3LQBPaI2YjGFtXexRAjt1I/MbfNlMx0sytSX3tn5hSLzQsR3Qy2rd0hc1BWojtj9w== dependencies: - "@jest/console" "^27.0.2" - "@jest/types" "^27.0.2" + "@jest/console" "^27.0.6" + "@jest/types" "^27.0.6" "@types/istanbul-lib-coverage" "^2.0.0" collect-v8-coverage "^1.0.0" -"@jest/test-sequencer@^27.0.5": - version "27.0.5" - resolved "https://registry.yarnpkg.com/@jest/test-sequencer/-/test-sequencer-27.0.5.tgz#c58b21db49afc36c0e3921d7ddf1fb7954abfded" - integrity sha512-opztnGs+cXzZ5txFG2+omBaV5ge/0yuJNKbhE3DREMiXE0YxBuzyEa6pNv3kk2JuucIlH2Xvgmn9kEEHSNt/SA== +"@jest/test-sequencer@^27.0.6": + version "27.0.6" + resolved "https://registry.yarnpkg.com/@jest/test-sequencer/-/test-sequencer-27.0.6.tgz#80a913ed7a1130545b1cd777ff2735dd3af5d34b" + integrity sha512-bISzNIApazYOlTHDum9PwW22NOyDa6VI31n6JucpjTVM0jD6JDgqEZ9+yn575nDdPF0+4csYDxNNW13NvFQGZA== dependencies: - "@jest/test-result" "^27.0.2" + "@jest/test-result" "^27.0.6" graceful-fs "^4.2.4" - jest-haste-map "^27.0.5" - jest-runtime "^27.0.5" + jest-haste-map "^27.0.6" + jest-runtime "^27.0.6" -"@jest/transform@^27.0.5": - version "27.0.5" - resolved "https://registry.yarnpkg.com/@jest/transform/-/transform-27.0.5.tgz#2dcb78953708af713941ac845b06078bc74ed873" - integrity sha512-lBD6OwKXSc6JJECBNk4mVxtSVuJSBsQrJ9WCBisfJs7EZuYq4K6vM9HmoB7hmPiLIDGeyaerw3feBV/bC4z8tg== +"@jest/transform@^27.0.6": + version "27.0.6" + resolved "https://registry.yarnpkg.com/@jest/transform/-/transform-27.0.6.tgz#189ad7107413208f7600f4719f81dd2f7278cc95" + integrity sha512-rj5Dw+mtIcntAUnMlW/Vju5mr73u8yg+irnHwzgtgoeI6cCPOvUwQ0D1uQtc/APmWgvRweEb1g05pkUpxH3iCA== dependencies: "@babel/core" "^7.1.0" - "@jest/types" "^27.0.2" + "@jest/types" "^27.0.6" babel-plugin-istanbul "^6.0.0" chalk "^4.0.0" convert-source-map "^1.4.0" fast-json-stable-stringify "^2.0.0" graceful-fs "^4.2.4" - jest-haste-map "^27.0.5" - jest-regex-util "^27.0.1" - jest-util "^27.0.2" + jest-haste-map "^27.0.6" + jest-regex-util "^27.0.6" + jest-util "^27.0.6" micromatch "^4.0.4" pirates "^4.0.1" slash "^3.0.0" source-map "^0.6.1" write-file-atomic "^3.0.0" -"@jest/types@^27.0.2": - version "27.0.2" - resolved "https://registry.yarnpkg.com/@jest/types/-/types-27.0.2.tgz#e153d6c46bda0f2589f0702b071f9898c7bbd37e" - integrity sha512-XpjCtJ/99HB4PmyJ2vgmN7vT+JLP7RW1FBT9RgnMFS4Dt7cvIyBee8O3/j98aUZ34ZpenPZFqmaaObWSeL65dg== +"@jest/types@^27.0.6": + version "27.0.6" + resolved "https://registry.yarnpkg.com/@jest/types/-/types-27.0.6.tgz#9a992bc517e0c49f035938b8549719c2de40706b" + integrity sha512-aSquT1qa9Pik26JK5/3rvnYb4bGtm1VFNesHKmNTwmPIgOrixvhL2ghIvFRNEpzy3gU+rUgjIF/KodbkFAl++g== dependencies: "@types/istanbul-lib-coverage" "^2.0.0" "@types/istanbul-reports" "^3.0.0" @@ -1559,54 +1688,54 @@ dependencies: "@octokit/openapi-types" "^7.3.2" -"@polkadot/api-contract@5.0.1": - version "5.0.1" - resolved "https://registry.yarnpkg.com/@polkadot/api-contract/-/api-contract-5.0.1.tgz#520a7b3cd990a76374b79e12eca5bf629cc565a1" - integrity sha512-qZ2wnXHDyU2c1/V9GKpbcZKBfVua4YFsU/LHKevZLkJfnGFBgNRdwAuKgVe5h2FCt2W2/pt618WgxG0UDWwjcw== +"@polkadot/api-contract@5.5.1": + version "5.5.1" + resolved "https://registry.yarnpkg.com/@polkadot/api-contract/-/api-contract-5.5.1.tgz#4cdd0d6f4352050c58464d5958bdb779770bd2dc" + integrity sha512-/1O1AnpCu+LM2EKhRY83r36blG8KOr0JCVFeSfT0u52tM4wMdLlUy1XV/XTZayuCucdJ6I0pjUudCljm92aiGw== dependencies: - "@babel/runtime" "^7.14.6" - "@polkadot/api" "5.0.1" - "@polkadot/types" "5.0.1" - "@polkadot/util" "^7.0.1" - rxjs "^7.2.0" + "@babel/runtime" "^7.15.3" + "@polkadot/api" "5.5.1" + "@polkadot/types" "5.5.1" + "@polkadot/util" "^7.2.1" + rxjs "^7.3.0" -"@polkadot/api-derive@5.0.1": - version "5.0.1" - resolved "https://registry.yarnpkg.com/@polkadot/api-derive/-/api-derive-5.0.1.tgz#08064c10ed159826ffd07013dcdde1d8b63186a0" - integrity sha512-JZpH1JVLu3PvX4+A71iDLtNr6LL103dAFou61DxyJF4obyTmS2lzigG3xXqUFShiPDb19ywxQpsE4gAOP6emuQ== +"@polkadot/api-derive@5.5.1": + version "5.5.1" + resolved "https://registry.yarnpkg.com/@polkadot/api-derive/-/api-derive-5.5.1.tgz#6fdba748d90024f2fcdeb7827d178ff8d0ad308e" + integrity sha512-dkpl3CnroBYAlLx571KoyjI72TqRweWI61z7tzNeR8qwniNyWDEILTErUfzy5jYAO7XrZpW1Gn4WMMH+kEcqZQ== dependencies: - "@babel/runtime" "^7.14.6" - "@polkadot/api" "5.0.1" - "@polkadot/rpc-core" "5.0.1" - "@polkadot/types" "5.0.1" - "@polkadot/util" "^7.0.1" - "@polkadot/util-crypto" "^7.0.1" - rxjs "^7.2.0" + "@babel/runtime" "^7.15.3" + "@polkadot/api" "5.5.1" + "@polkadot/rpc-core" "5.5.1" + "@polkadot/types" "5.5.1" + "@polkadot/util" "^7.2.1" + "@polkadot/util-crypto" "^7.2.1" + rxjs "^7.3.0" -"@polkadot/api@5.0.1": - version "5.0.1" - resolved "https://registry.yarnpkg.com/@polkadot/api/-/api-5.0.1.tgz#9607b53009322f9264f7dcc8705c466bd33aa516" - integrity sha512-5JDpM2Fjc80gHBju1B/rMBGDfAvY8UiU4XVlivJRk+mTVD3OTwbtTro4nmwJOub05xQCJvD/bnCuxG8eFSoq+Q== +"@polkadot/api@5.5.1": + version "5.5.1" + resolved "https://registry.yarnpkg.com/@polkadot/api/-/api-5.5.1.tgz#0298c6d883c2264a68ae93a3b59b98263aed53d3" + integrity sha512-GS/MoRc7NB61jz7TzwX0WAA3JS7DSj3xH4ac39LcuPHXu0VMQw6LgT/5KIzYxTx+79Iwth62bKelW/Mgk23wUg== dependencies: - "@babel/runtime" "^7.14.6" - "@polkadot/api-derive" "5.0.1" - "@polkadot/keyring" "^7.0.1" - "@polkadot/rpc-core" "5.0.1" - "@polkadot/rpc-provider" "5.0.1" - "@polkadot/types" "5.0.1" - "@polkadot/types-known" "5.0.1" - "@polkadot/util" "^7.0.1" - "@polkadot/util-crypto" "^7.0.1" + "@babel/runtime" "^7.15.3" + "@polkadot/api-derive" "5.5.1" + "@polkadot/keyring" "^7.2.1" + "@polkadot/rpc-core" "5.5.1" + "@polkadot/rpc-provider" "5.5.1" + "@polkadot/types" "5.5.1" + "@polkadot/types-known" "5.5.1" + "@polkadot/util" "^7.2.1" + "@polkadot/util-crypto" "^7.2.1" eventemitter3 "^4.0.7" - rxjs "^7.2.0" + rxjs "^7.3.0" -"@polkadot/dev@0.62.43": - version "0.62.43" - resolved "https://registry.yarnpkg.com/@polkadot/dev/-/dev-0.62.43.tgz#567591bf3c38dded4b4c1f3ec8bf3d3198a23b6d" - integrity sha512-ZSgYUbC6A+WtRSY5nq7yeGYW+wv3g8cds2zndL4GeClIdVHksgEW6+ch3Hx6LMkE3y4q9Kjvs50oHeemBDut4Q== +"@polkadot/dev@0.62.60": + version "0.62.60" + resolved "https://registry.yarnpkg.com/@polkadot/dev/-/dev-0.62.60.tgz#450007c189a8433d8627bcc1fc01d2ffb1becfc3" + integrity sha512-VHZ4d/hhRSNFe0RXp3L/ZcAk1t2JQ1/lsznONAz4I9SZ2pn5kAQrWRF6eukgfQscrlqCH5njDAxwgXe6ODNVRw== dependencies: - "@babel/cli" "^7.14.5" - "@babel/core" "^7.14.6" + "@babel/cli" "^7.14.8" + "@babel/core" "^7.15.0" "@babel/plugin-proposal-class-properties" "^7.14.5" "@babel/plugin-proposal-nullish-coalescing-operator" "^7.14.5" "@babel/plugin-proposal-numeric-separator" "^7.14.5" @@ -1618,28 +1747,34 @@ "@babel/plugin-syntax-import-meta" "^7.10.4" "@babel/plugin-syntax-top-level-await" "^7.14.5" "@babel/plugin-transform-regenerator" "^7.14.5" - "@babel/plugin-transform-runtime" "^7.14.5" - "@babel/preset-env" "^7.14.7" + "@babel/plugin-transform-runtime" "^7.15.0" + "@babel/preset-env" "^7.15.0" "@babel/preset-react" "^7.14.5" - "@babel/preset-typescript" "^7.14.5" - "@babel/register" "^7.14.5" - "@babel/runtime" "^7.14.6" + "@babel/preset-typescript" "^7.15.0" + "@babel/register" "^7.15.3" + "@babel/runtime" "^7.15.3" + "@rollup/plugin-alias" "^3.1.5" + "@rollup/plugin-commonjs" "^19.0.2" + "@rollup/plugin-inject" "^4.0.2" + "@rollup/plugin-json" "^4.1.0" + "@rollup/plugin-node-resolve" "^13.0.4" "@rushstack/eslint-patch" "^1.0.6" - "@typescript-eslint/eslint-plugin" "4.28.0" - "@typescript-eslint/parser" "4.28.0" + "@typescript-eslint/eslint-plugin" "4.29.2" + "@typescript-eslint/parser" "4.29.2" "@vue/component-compiler-utils" "^3.2.2" - babel-jest "^27.0.5" + babel-jest "^27.0.6" babel-plugin-module-extension-resolver "^1.0.0-rc.2" babel-plugin-module-resolver "^4.1.0" - babel-plugin-styled-components "^1.12.0" - browserslist "^4.16.6" - chalk "^4.1.1" - coveralls "^3.1.0" - eslint "^7.29.0" + babel-plugin-styled-components "^1.13.2" + browserslist "^4.16.7" + chalk "^4.1.2" + coveralls "^3.1.1" + eslint "^7.32.0" eslint-config-standard "^16.0.3" - eslint-import-resolver-node "^0.3.4" + eslint-import-resolver-node "^0.3.6" eslint-plugin-header "^3.1.1" - eslint-plugin-import "^2.23.4" + eslint-plugin-import "^2.24.0" + eslint-plugin-import-newlines "^1.1.4" eslint-plugin-node "^11.1.0" eslint-plugin-promise "^5.1.0" eslint-plugin-react "^7.24.0" @@ -1651,118 +1786,129 @@ gh-release "^6.0.0" glob "^7.1.7" glob2base "^0.0.12" - jest "^27.0.5" - jest-cli "^27.0.5" - jest-config "^27.0.5" - jest-haste-map "^27.0.5" - jest-resolve "^27.0.5" + jest "^27.0.6" + jest-cli "^27.0.6" + jest-config "^27.0.6" + jest-haste-map "^27.0.6" + jest-resolve "^27.0.6" madge "^4.0.2" minimatch "^3.0.4" mkdirp "^1.0.4" - prettier "^2.3.1" + prettier "^2.3.2" rimraf "^3.0.2" - typescript "^4.3.4" - yargs "^17.0.1" + rollup "^2.56.2" + typescript "^4.3.5" + yargs "^17.1.1" -"@polkadot/keyring@^7.0.1": - version "7.0.1" - resolved "https://registry.yarnpkg.com/@polkadot/keyring/-/keyring-7.0.1.tgz#666e903661b98279dc16d512be69f5ace4b58d8d" - integrity sha512-eSvG8Q4gUTRDFWj2lqTY/9NekGP8dtp+W6WmouKh0DDwHRawaVeDaq6UJYQv6XoBG1i+ZGPvErRQeGMPOn/mUQ== +"@polkadot/keyring@^7.2.1": + version "7.2.1" + resolved "https://registry.yarnpkg.com/@polkadot/keyring/-/keyring-7.2.1.tgz#5ed8e6c0edc61e3dd99ee647a227b9e3d955e8e6" + integrity sha512-WmiTsHKELX16uZWLvebDBckZIAXeJFfbcOM6m/VbMOjSV5C6xIKqiV3232Mn8ZuPKgsOf25Q78/IwJW1Dq53Qg== dependencies: - "@babel/runtime" "^7.14.6" - "@polkadot/util" "7.0.1" - "@polkadot/util-crypto" "7.0.1" + "@babel/runtime" "^7.15.3" + "@polkadot/util" "7.2.1" + "@polkadot/util-crypto" "7.2.1" -"@polkadot/networks@7.0.1", "@polkadot/networks@^7.0.1": - version "7.0.1" - resolved "https://registry.yarnpkg.com/@polkadot/networks/-/networks-7.0.1.tgz#e07c4b88e25711433e76d24fce4c7273c25dd38b" - integrity sha512-bJSvI7UgEpxmBKS8TMh+I1mfmCMwhClGdSs29kwU+K61IjBTKTt3yQJ/SflYIQV7QftGbz3oMfSkGbQbRHZqvQ== +"@polkadot/networks@7.2.1", "@polkadot/networks@^7.2.1": + version "7.2.1" + resolved "https://registry.yarnpkg.com/@polkadot/networks/-/networks-7.2.1.tgz#20c8d81fba4b48162bf360759d8d54c55d30128b" + integrity sha512-YX8oQ7QQ2oq3YowwOiv/C82l849V0ZEzpR26YrPgKSXbYFbasho3Akf0zalndZJZV1Bb8EiOkzGoJ3ffogSPxA== dependencies: - "@babel/runtime" "^7.14.6" + "@babel/runtime" "^7.15.3" -"@polkadot/rpc-core@5.0.1": - version "5.0.1" - resolved "https://registry.yarnpkg.com/@polkadot/rpc-core/-/rpc-core-5.0.1.tgz#8460287532fe61c31505564df53e92ef6feba875" - integrity sha512-JMNOVQijjyJZNu9B8CJwIrQzGYzAp03uCBSbqYfzWBFnYVLKh7JmvOlkLnODM8uUYq0gVN4BaDUSPc39GpELAQ== +"@polkadot/rpc-core@5.5.1": + version "5.5.1" + resolved "https://registry.yarnpkg.com/@polkadot/rpc-core/-/rpc-core-5.5.1.tgz#4ce0646becabe7736dfb81eb902e5933158646c8" + integrity sha512-hP7a55iSpgZVqxAIpK+v63eV/nD14Tm7C1rUmfKIS6gGJFJf+sQbTmp6d7+fuKxvYfFqBrFLU8IraOhLOQ5W3Q== dependencies: - "@babel/runtime" "^7.14.6" - "@polkadot/rpc-provider" "5.0.1" - "@polkadot/types" "5.0.1" - "@polkadot/util" "^7.0.1" - rxjs "^7.2.0" + "@babel/runtime" "^7.15.3" + "@polkadot/rpc-provider" "5.5.1" + "@polkadot/types" "5.5.1" + "@polkadot/util" "^7.2.1" + rxjs "^7.3.0" -"@polkadot/rpc-provider@5.0.1": - version "5.0.1" - resolved "https://registry.yarnpkg.com/@polkadot/rpc-provider/-/rpc-provider-5.0.1.tgz#ef022a123eb9073634b59c6e0f6e1705e96066a5" - integrity sha512-t+VKhMtQfQVgkZDqYnP/44KlBDmcCVo1/MvJ+DoNd7RUWUIBJt3v71G5gDSNeGMTyvxn0KK0qL4j+Nqr6c4FUQ== +"@polkadot/rpc-provider@5.5.1": + version "5.5.1" + resolved "https://registry.yarnpkg.com/@polkadot/rpc-provider/-/rpc-provider-5.5.1.tgz#633f4a48605623092fb9017433f2b3cd70cd96bc" + integrity sha512-wOCKeeyUa7Dw3nxKkQntnfOO471icdzqT2V7bwloBOo+G2MX8nHImO0mW3QMfJygn4qoARF1PBo1PLbDUEDgog== dependencies: - "@babel/runtime" "^7.14.6" - "@polkadot/types" "5.0.1" - "@polkadot/util" "^7.0.1" - "@polkadot/util-crypto" "^7.0.1" - "@polkadot/x-fetch" "^7.0.1" - "@polkadot/x-global" "^7.0.1" - "@polkadot/x-ws" "^7.0.1" + "@babel/runtime" "^7.15.3" + "@polkadot/types" "5.5.1" + "@polkadot/util" "^7.2.1" + "@polkadot/util-crypto" "^7.2.1" + "@polkadot/x-fetch" "^7.2.1" + "@polkadot/x-global" "^7.2.1" + "@polkadot/x-ws" "^7.2.1" eventemitter3 "^4.0.7" -"@polkadot/ts@0.3.89": - version "0.3.89" - resolved "https://registry.yarnpkg.com/@polkadot/ts/-/ts-0.3.89.tgz#c7a704ea284d04fcf4d581f5df156d5945480033" - integrity sha512-GC0H8wmVKebkieN2MHScjDDonzigIzkjl1Q4V1OhoRcfQbeZZ7vijeiVwP8Hw3wIw4GLKxxXeDrkKPWl/bcaHw== +"@polkadot/ts@0.4.4": + version "0.4.4" + resolved "https://registry.yarnpkg.com/@polkadot/ts/-/ts-0.4.4.tgz#e86aa47c2bcbc70ac8385b31014c81927c4b0a88" + integrity sha512-lzB8lg8GfdJlA7RdeoOJVFopecN4i++JndbUs6jW7AgRz+joeXQIIRomVgCNE52nW1uWpXMELnlvEP812v7sVw== dependencies: - "@types/chrome" "^0.0.144" + "@types/chrome" "^0.0.145" -"@polkadot/typegen@5.0.1": - version "5.0.1" - resolved "https://registry.yarnpkg.com/@polkadot/typegen/-/typegen-5.0.1.tgz#718b517f4f1578441911096603577bd0a2a968e0" - integrity sha512-iFLJoWgIkn+J6MDw3AUWveP9qxVn1C+VeLJbpZ21St5WyeE148Tml0BmYnKLSXlaPMhZEwB+/IV3jpQ35dH4bw== +"@polkadot/typegen@5.5.1": + version "5.5.1" + resolved "https://registry.yarnpkg.com/@polkadot/typegen/-/typegen-5.5.1.tgz#b31010716a142290d12f48ead6166851599055d0" + integrity sha512-ua55CVqT3+Y5fX9stpYUO+UhiJJ1RDTZ6vM2/Lndmsuda4lHQnUDrCnMmxKhM5OcyIlJlY5mF9dyO0kl5mTm+w== dependencies: - "@babel/core" "^7.14.6" - "@babel/register" "^7.14.5" - "@babel/runtime" "^7.14.6" - "@polkadot/api" "5.0.1" - "@polkadot/rpc-provider" "5.0.1" - "@polkadot/types" "5.0.1" - "@polkadot/util" "^7.0.1" + "@babel/core" "^7.15.0" + "@babel/register" "^7.15.3" + "@babel/runtime" "^7.15.3" + "@polkadot/api" "5.5.1" + "@polkadot/rpc-provider" "5.5.1" + "@polkadot/types" "5.5.1" + "@polkadot/types-support" "5.5.1" + "@polkadot/util" "^7.2.1" handlebars "^4.7.7" websocket "^1.0.34" - yargs "^17.0.1" + yargs "^17.1.0" -"@polkadot/types-known@5.0.1": - version "5.0.1" - resolved "https://registry.yarnpkg.com/@polkadot/types-known/-/types-known-5.0.1.tgz#21feb327fc4323733bf027c8d874a2aa3014b21f" - integrity sha512-AIhPlN4r14ZW4wdwHZD2nIe1DE61ZO9PsyrCyAU3ysl6Cw6TI+txDCN3aS/8XYuC7wDLEgLB9vJv2sVWdCzqJg== +"@polkadot/types-known@5.5.1": + version "5.5.1" + resolved "https://registry.yarnpkg.com/@polkadot/types-known/-/types-known-5.5.1.tgz#b00b0d45cbd07b4e0c3199f8ba00d10a1bd3f63d" + integrity sha512-bxBRmZ0a3lwEyWkWOKqmDJfpNKh3cp9xo6IidrQU2S5OPMjFFercB+HwJjkNE1cMtShwBYTvDheUImNkdm+FXA== dependencies: - "@babel/runtime" "^7.14.6" - "@polkadot/networks" "^7.0.1" - "@polkadot/types" "5.0.1" - "@polkadot/util" "^7.0.1" + "@babel/runtime" "^7.15.3" + "@polkadot/networks" "^7.2.1" + "@polkadot/types" "5.5.1" + "@polkadot/util" "^7.2.1" -"@polkadot/types@5.0.1": - version "5.0.1" - resolved "https://registry.yarnpkg.com/@polkadot/types/-/types-5.0.1.tgz#2a4e23e452f999eeae175b595470df0e426a930d" - integrity sha512-aN6JKeF7ZYi5irYAaUoDqth6qlOlB15C5vhlDOojEorYLfRs/R+GCrO+lPSs+bKmSxh7BSRh500ikI/xD4nx5A== +"@polkadot/types-support@5.5.1": + version "5.5.1" + resolved "https://registry.yarnpkg.com/@polkadot/types-support/-/types-support-5.5.1.tgz#15556c2f31e79f0a6a821c7723f702757cb89462" + integrity sha512-57i1SdK8B+miGTAlDNdvbBuN6FguTnwzv2UPE2Zv3iQznTSZBkQZN16tIK/yMkQfhtO4ZzPcAnnSPZMncqh/Mg== dependencies: - "@babel/runtime" "^7.14.6" - "@polkadot/util" "^7.0.1" - "@polkadot/util-crypto" "^7.0.1" - rxjs "^7.2.0" + "@babel/runtime" "^7.15.3" + "@polkadot/util" "^7.2.1" + +"@polkadot/types@5.5.1": + version "5.5.1" + resolved "https://registry.yarnpkg.com/@polkadot/types/-/types-5.5.1.tgz#057e8f0fc2369c0741c0f9b0224418e8f25a6938" + integrity sha512-+Cm7Y6D/98WqL8ofONyZrVvE2CxzK3/z18bATIQIWhG2w9ir9PdWaFMZ3fLCRw2Ggaq88AknguK6kXeEPcKPrA== + dependencies: + "@babel/runtime" "^7.15.3" + "@polkadot/util" "^7.2.1" + "@polkadot/util-crypto" "^7.2.1" + rxjs "^7.3.0" -"@polkadot/util-crypto@7.0.1", "@polkadot/util-crypto@^7.0.1": - version "7.0.1" - resolved "https://registry.yarnpkg.com/@polkadot/util-crypto/-/util-crypto-7.0.1.tgz#03109dc11323dad174fb2214d395855495def16a" - integrity sha512-dbvdsICoyOVw/K45RmHOP7wXE/7vj+NzEKGcKbiDt39nglHm6g2BTJ947PwwyNusTTAx82Q2iJ9vIZ1Kl0xG+g== +"@polkadot/util-crypto@7.2.1", "@polkadot/util-crypto@^7.2.1": + version "7.2.1" + resolved "https://registry.yarnpkg.com/@polkadot/util-crypto/-/util-crypto-7.2.1.tgz#7f1bbf031dac75090699083fc9e825c22e5d5f61" + integrity sha512-X3iGba/1JTL/0MNzMNEIlO9DNyKlwFV839jfGLDKhPbCuDmWp0NdQjF3mBmbvNwkXvn07WmhE7g3q9n5iTzqvQ== dependencies: - "@babel/runtime" "^7.14.6" - "@polkadot/networks" "7.0.1" - "@polkadot/util" "7.0.1" + "@babel/runtime" "^7.15.3" + "@polkadot/networks" "7.2.1" + "@polkadot/util" "7.2.1" "@polkadot/wasm-crypto" "^4.1.2" - "@polkadot/x-randomvalues" "7.0.1" + "@polkadot/x-randomvalues" "7.2.1" base-x "^3.0.8" base64-js "^1.5.1" blakejs "^1.1.1" bn.js "^4.11.9" create-hash "^1.2.0" + ed2curve "^0.3.0" elliptic "^6.5.4" hash.js "^1.1.7" js-sha3 "^0.8.0" @@ -1770,14 +1916,14 @@ tweetnacl "^1.0.3" xxhashjs "^0.2.2" -"@polkadot/util@7.0.1", "@polkadot/util@^7.0.1": - version "7.0.1" - resolved "https://registry.yarnpkg.com/@polkadot/util/-/util-7.0.1.tgz#79afd40473016876f51d65ebb9900a20108fe0a4" - integrity sha512-EtQlZL6ok0Ep+zRz2QHMUoJo/b3kFHVN2qqyD2+9sdqg0FGLmkzNFM+K6dasCMLXieJ1l0HoFsQppSo/leUeaA== +"@polkadot/util@7.2.1", "@polkadot/util@^7.2.1": + version "7.2.1" + resolved "https://registry.yarnpkg.com/@polkadot/util/-/util-7.2.1.tgz#abcad49f884534ff042c37480f63b9750c69341d" + integrity sha512-GilFg3i5dmu0H6dHEyh5bUw3yywmnFpEHfxFmKghL1ABDEr4qD0d/XAJ9UrzLFCBKbdTZsR0MDjgjVI2N84J1A== dependencies: - "@babel/runtime" "^7.14.6" - "@polkadot/x-textdecoder" "7.0.1" - "@polkadot/x-textencoder" "7.0.1" + "@babel/runtime" "^7.15.3" + "@polkadot/x-textdecoder" "7.2.1" + "@polkadot/x-textencoder" "7.2.1" "@types/bn.js" "^4.11.6" bn.js "^4.11.9" camelcase "^5.3.1" @@ -1806,57 +1952,114 @@ "@polkadot/wasm-crypto-asmjs" "^4.1.2" "@polkadot/wasm-crypto-wasm" "^4.1.2" -"@polkadot/x-fetch@^7.0.1": - version "7.0.1" - resolved "https://registry.yarnpkg.com/@polkadot/x-fetch/-/x-fetch-7.0.1.tgz#2db6fa19f4f4d9b2f4cf50ba78bf3aa947d7b982" - integrity sha512-9R38FjtlJcvdpEA7tVGmTmH4aiBCTABuLJdVSn3cYkgWfxDHeFMqjdFzTJ6Asa5cY0Ds3ZKsh9uccTQBQzV/HQ== +"@polkadot/x-fetch@^7.2.1": + version "7.2.1" + resolved "https://registry.yarnpkg.com/@polkadot/x-fetch/-/x-fetch-7.2.1.tgz#c9bee0316d31cd150b2cb6646ccdb77c6dc3d42d" + integrity sha512-osdZNPfrB50d7tfjVs4QRjfsb6xqC09JEeYzbUl24hUXPwtkQE8/379jayu1usPe9/JI2wKYGscdf/nRl4pBkA== dependencies: - "@babel/runtime" "^7.14.6" - "@polkadot/x-global" "7.0.1" - "@types/node-fetch" "^2.5.11" + "@babel/runtime" "^7.15.3" + "@polkadot/x-global" "7.2.1" + "@types/node-fetch" "^2.5.12" node-fetch "^2.6.1" -"@polkadot/x-global@7.0.1", "@polkadot/x-global@^7.0.1": - version "7.0.1" - resolved "https://registry.yarnpkg.com/@polkadot/x-global/-/x-global-7.0.1.tgz#44fb248d3aaea557753318327149772969e96bff" - integrity sha512-gVVACSdRhHYRJejLEAL0mM9BZfY8N50VT2+15A7ALD1tVqwS4tz3P9vRW3Go7ZjfyAc83aEmh0PiQ8Nm1R+2Cg== +"@polkadot/x-global@7.2.1", "@polkadot/x-global@^7.2.1": + version "7.2.1" + resolved "https://registry.yarnpkg.com/@polkadot/x-global/-/x-global-7.2.1.tgz#32207936b7f939a21da608f82ca20535f9148cda" + integrity sha512-VNW+76TxEPqvBy3XMNV05mJRPRGZcYh3k5HjW4+asYeFunMahH4zjmCulhtD9SRI/TqdfHTiqDOqKNKe2xJcVg== dependencies: - "@babel/runtime" "^7.14.6" + "@babel/runtime" "^7.15.3" -"@polkadot/x-randomvalues@7.0.1": - version "7.0.1" - resolved "https://registry.yarnpkg.com/@polkadot/x-randomvalues/-/x-randomvalues-7.0.1.tgz#32036ae5d48645a062f6a1c3ebbf227236c806b8" - integrity sha512-UNoIFaz1xJPozruT+lo8BTeT8A3NM3PgWuru7Vs8OsIz0Phkg7lUWlpHu9PZHyQCyKlUryvkOA692IlVlNYy2Q== +"@polkadot/x-randomvalues@7.2.1": + version "7.2.1" + resolved "https://registry.yarnpkg.com/@polkadot/x-randomvalues/-/x-randomvalues-7.2.1.tgz#708b7a54bd90ec091ab54e125d8b52e0853ea86b" + integrity sha512-B4sjwX+gFweZ1YM1Cg/S9hAEx9E/gV/vqLW89PJB6+hyvsPS9eiVvfVpaOsohc7AgmuINm/bSQbNZvtC+BbbKw== dependencies: - "@babel/runtime" "^7.14.6" - "@polkadot/x-global" "7.0.1" + "@babel/runtime" "^7.15.3" + "@polkadot/x-global" "7.2.1" -"@polkadot/x-textdecoder@7.0.1": - version "7.0.1" - resolved "https://registry.yarnpkg.com/@polkadot/x-textdecoder/-/x-textdecoder-7.0.1.tgz#bb9bba94b2eb1612dd35c299f43ab74515db74d9" - integrity sha512-CFRnpI0cp1h2N1+ec551BLVLwV6OHG6Gj62EYcIOXR+o/SX/6MXm3Qcehm2YvfTKqktyIUSWmTwbWjGjuqPrpA== +"@polkadot/x-textdecoder@7.2.1": + version "7.2.1" + resolved "https://registry.yarnpkg.com/@polkadot/x-textdecoder/-/x-textdecoder-7.2.1.tgz#c52074dba9943a12583f3f8672a49399f10e00f3" + integrity sha512-yXSZ0P/D/8HT8gbkdTjw/1AKZIVbX3+mIfiDiN3VqUBzruV7ak5hA+D01I0woBGDqxWISoLQFtGrxPAQ8pwAcg== dependencies: - "@babel/runtime" "^7.14.6" - "@polkadot/x-global" "7.0.1" + "@babel/runtime" "^7.15.3" + "@polkadot/x-global" "7.2.1" -"@polkadot/x-textencoder@7.0.1": - version "7.0.1" - resolved "https://registry.yarnpkg.com/@polkadot/x-textencoder/-/x-textencoder-7.0.1.tgz#181d403c5dc1d94fd1e2147fd1c5c528d30d8805" - integrity sha512-m+QL1HNiu5GMz6cfr/udSA6fUTv3RyIybJb7v43EQCxqlj/L0J3cUHapFd6tqH9PElD6jPkH1pXcgYN8e7dWTQ== +"@polkadot/x-textencoder@7.2.1": + version "7.2.1" + resolved "https://registry.yarnpkg.com/@polkadot/x-textencoder/-/x-textencoder-7.2.1.tgz#2326b3b7f9a5e445d7e560c438effbe800e2b1f6" + integrity sha512-1aqfxmfKSOWeOxmGBmk+RYrpqGtWywS6t0y/R3FI+k+s8NfIfGdcjMcupKq7khPh92PvVGkur+CnM/y6chn4XA== dependencies: - "@babel/runtime" "^7.14.6" - "@polkadot/x-global" "7.0.1" + "@babel/runtime" "^7.15.3" + "@polkadot/x-global" "7.2.1" -"@polkadot/x-ws@^7.0.1": - version "7.0.1" - resolved "https://registry.yarnpkg.com/@polkadot/x-ws/-/x-ws-7.0.1.tgz#8c22a61c0dd9b82865c7631e22ac147c2b73b118" - integrity sha512-VUn/6sCJUpvW9WhUK+DKo1uDrw4yO84twRcy5JSzvSiBTaSplhU9Q4qGFl2Atr3WIzAYYx1jQSm/j6AhPRji1w== +"@polkadot/x-ws@^7.2.1": + version "7.2.1" + resolved "https://registry.yarnpkg.com/@polkadot/x-ws/-/x-ws-7.2.1.tgz#5971ab630911cdecd0a46db6fb899e9086954e58" + integrity sha512-sYnOF0qNdMuGFiRGWAtpkQQYIP44JFzGywap0CskhNEyCc+zDBi4l/ta3qHjeGta+h9rdVjDeYk2J86EsKlkSw== dependencies: - "@babel/runtime" "^7.14.6" - "@polkadot/x-global" "7.0.1" - "@types/websocket" "^1.0.3" + "@babel/runtime" "^7.15.3" + "@polkadot/x-global" "7.2.1" + "@types/websocket" "^1.0.4" websocket "^1.0.34" +"@rollup/plugin-alias@^3.1.5": + version "3.1.5" + resolved "https://registry.yarnpkg.com/@rollup/plugin-alias/-/plugin-alias-3.1.5.tgz#73356a3a1eab2e1e2fd952f9f53cd89fc740d952" + integrity sha512-yzUaSvCC/LJPbl9rnzX3HN7vy0tq7EzHoEiQl1ofh4n5r2Rd5bj/+zcJgaGA76xbw95/JjWQyvHg9rOJp2y0oQ== + dependencies: + slash "^3.0.0" + +"@rollup/plugin-commonjs@^19.0.2": + version "19.0.2" + resolved "https://registry.yarnpkg.com/@rollup/plugin-commonjs/-/plugin-commonjs-19.0.2.tgz#1ccc3d63878d1bc9846f8969f09dd3b3e4ecc244" + integrity sha512-gBjarfqlC7qs0AutpRW/hrFNm+cd2/QKxhwyFa+srbg1oX7rDsEU3l+W7LAUhsAp9mPJMAkXDhLbQaVwEaE8bA== + dependencies: + "@rollup/pluginutils" "^3.1.0" + commondir "^1.0.1" + estree-walker "^2.0.1" + glob "^7.1.6" + is-reference "^1.2.1" + magic-string "^0.25.7" + resolve "^1.17.0" + +"@rollup/plugin-inject@^4.0.2": + version "4.0.2" + resolved "https://registry.yarnpkg.com/@rollup/plugin-inject/-/plugin-inject-4.0.2.tgz#55b21bb244a07675f7fdde577db929c82fc17395" + integrity sha512-TSLMA8waJ7Dmgmoc8JfPnwUwVZgLjjIAM6MqeIFqPO2ODK36JqE0Cf2F54UTgCUuW8da93Mvoj75a6KAVWgylw== + dependencies: + "@rollup/pluginutils" "^3.0.4" + estree-walker "^1.0.1" + magic-string "^0.25.5" + +"@rollup/plugin-json@^4.1.0": + version "4.1.0" + resolved "https://registry.yarnpkg.com/@rollup/plugin-json/-/plugin-json-4.1.0.tgz#54e09867ae6963c593844d8bd7a9c718294496f3" + integrity sha512-yfLbTdNS6amI/2OpmbiBoW12vngr5NW2jCJVZSBEz+H5KfUJZ2M7sDjk0U6GOOdCWFVScShte29o9NezJ53TPw== + dependencies: + "@rollup/pluginutils" "^3.0.8" + +"@rollup/plugin-node-resolve@^13.0.4": + version "13.0.4" + resolved "https://registry.yarnpkg.com/@rollup/plugin-node-resolve/-/plugin-node-resolve-13.0.4.tgz#b10222f4145a019740acb7738402130d848660c0" + integrity sha512-eYq4TFy40O8hjeDs+sIxEH/jc9lyuI2k9DM557WN6rO5OpnC2qXMBNj4IKH1oHrnAazL49C5p0tgP0/VpqJ+/w== + dependencies: + "@rollup/pluginutils" "^3.1.0" + "@types/resolve" "1.17.1" + builtin-modules "^3.1.0" + deepmerge "^4.2.2" + is-module "^1.0.0" + resolve "^1.19.0" + +"@rollup/pluginutils@^3.0.4", "@rollup/pluginutils@^3.0.8", "@rollup/pluginutils@^3.1.0": + version "3.1.0" + resolved "https://registry.yarnpkg.com/@rollup/pluginutils/-/pluginutils-3.1.0.tgz#706b4524ee6dc8b103b3c995533e5ad680c02b9b" + integrity sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg== + dependencies: + "@types/estree" "0.0.39" + estree-walker "^1.0.1" + picomatch "^2.2.2" + "@rushstack/eslint-patch@^1.0.6": version "1.0.6" resolved "https://registry.yarnpkg.com/@rushstack/eslint-patch/-/eslint-patch-1.0.6.tgz#023d72a5c4531b4ce204528971700a78a85a0c50" @@ -1945,14 +2148,24 @@ resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.2.18.tgz#0c8e298dbff8205e2266606c1ea5fbdba29b46e4" integrity sha512-rS27+EkB/RE1Iz3u0XtVL5q36MGDWbgYe7zWiodyKNUnthxY0rukK5V36eiUCtCisB7NN8zKYH6DO2M37qxFEQ== -"@types/chrome@^0.0.144": - version "0.0.144" - resolved "https://registry.yarnpkg.com/@types/chrome/-/chrome-0.0.144.tgz#7dd9188e355aa17e3ad397f50b5cd3ad12caf788" - integrity sha512-BgoiO7/KP9hRNrCR2Wq+aKWT5Dh9bTofuWaRtcqPcj8YKhZojQgb6sSdIqvds2C+eO63BwaR9KHVMYYgZdGGBg== +"@types/chrome@^0.0.145": + version "0.0.145" + resolved "https://registry.yarnpkg.com/@types/chrome/-/chrome-0.0.145.tgz#6c53ae0af5f25350b07bfd24cf459b5fe65cd9b8" + integrity sha512-vLvTMmfc8mvwOZzkmn2UwlWSNu0t0txBkyuIv8NgihRkvFCe6XJX65YZAgAP/RdBit3enhU2GTxCr+prn4uZmA== dependencies: "@types/filesystem" "*" "@types/har-format" "*" +"@types/estree@*": + version "0.0.50" + resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.50.tgz#1e0caa9364d3fccd2931c3ed96fdbeaa5d4cca83" + integrity sha512-C6N5s2ZFtuZRj54k2/zyRhNDjJwwcViAM3Nbm8zjBpbqAdZ00mr0CFxvSKeO8Y/e03WVFLpQMdHYVfUd6SB+Hw== + +"@types/estree@0.0.39": + version "0.0.39" + resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.39.tgz#e177e699ee1b8c22d23174caaa7422644389509f" + integrity sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw== + "@types/filesystem@*": version "0.0.30" resolved "https://registry.yarnpkg.com/@types/filesystem/-/filesystem-0.0.30.tgz#a7373a2edf34d13e298baf7ee1101f738b2efb7e" @@ -2011,10 +2224,10 @@ resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-8.2.2.tgz#91daa226eb8c2ff261e6a8cbf8c7304641e095e0" integrity sha512-Lwh0lzzqT5Pqh6z61P3c3P5nm6fzQK/MMHl9UKeneAeInVflBSz1O2EkX6gM6xfJd7FBXBY5purtLx7fUiZ7Hw== -"@types/node-fetch@^2.5.11": - version "2.5.11" - resolved "https://registry.yarnpkg.com/@types/node-fetch/-/node-fetch-2.5.11.tgz#ce22a2e65fc8999f4dbdb7ddbbcf187d755169e4" - integrity sha512-2upCKaqVZETDRb8A2VTaRymqFBEgH8u6yr96b/u3+1uQEPDRo3mJLEiPk7vdXBHRtjwkjqzFYMJXrt0Z9QsYjQ== +"@types/node-fetch@^2.5.12": + version "2.5.12" + resolved "https://registry.yarnpkg.com/@types/node-fetch/-/node-fetch-2.5.12.tgz#8a6f779b1d4e60b7a57fb6fd48d84fb545b9cc66" + integrity sha512-MKgC4dlq4kKNa/mYrwpKfzQMB5X3ee5U6fSprkKpToBqBmX4nFZL9cW5jl6sWn+xpRJ7ypWh2yyqqr8UUCstSw== dependencies: "@types/node" "*" form-data "^3.0.0" @@ -2046,6 +2259,13 @@ resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.3.0.tgz#2e8332cc7363f887d32ec5496b207d26ba8052bb" integrity sha512-hkc1DATxFLQo4VxPDpMH1gCkPpBbpOoJ/4nhuXw4n63/0R6bCpQECj4+K226UJ4JO/eJQz+1mC2I7JsWanAdQw== +"@types/resolve@1.17.1": + version "1.17.1" + resolved "https://registry.yarnpkg.com/@types/resolve/-/resolve-1.17.1.tgz#3afd6ad8967c77e4376c598a82ddd58f46ec45d6" + integrity sha512-yy7HuzQhj0dhGpD8RLXSZWEkLsV9ibvxvi6EiJ3bkqLAO1RGo0WbkWQiwpRlSFymTJRz0d3k5LM3kkx8ArDbLw== + dependencies: + "@types/node" "*" + "@types/secp256k1@^4.0.1": version "4.0.2" resolved "https://registry.yarnpkg.com/@types/secp256k1/-/secp256k1-4.0.2.tgz#20c29a87149d980f64464e56539bf4810fdb5d1d" @@ -2058,10 +2278,10 @@ resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-2.0.0.tgz#7036640b4e21cc2f259ae826ce843d277dad8cff" integrity sha512-RJJrrySY7A8havqpGObOB4W92QXKJo63/jFLLgpvOtsGUqbQZ9Sbgl35KMm1DjC6j7AvmmU2bIno+3IyEaemaw== -"@types/websocket@^1.0.3": - version "1.0.3" - resolved "https://registry.yarnpkg.com/@types/websocket/-/websocket-1.0.3.tgz#49e09f939afd0ccdee4f7108d4712ec9feb0f153" - integrity sha512-ZdoTSwmDsKR7l1I8fpfQtmTI/hUwlOvE3q0iyJsp4tXU0MkdrYowimDzwxjhQvxU4qjhHLd3a6ig0OXRbLgIdw== +"@types/websocket@^1.0.4": + version "1.0.4" + resolved "https://registry.yarnpkg.com/@types/websocket/-/websocket-1.0.4.tgz#1dc497280d8049a5450854dd698ee7e6ea9e60b8" + integrity sha512-qn1LkcFEKK8RPp459jkjzsfpbsx36BBt3oC3pITYtkoBw/aVX+EZFa5j3ThCRTNpLFvIMr5dSTD4RaMdilIOpA== dependencies: "@types/node" "*" @@ -2077,13 +2297,13 @@ dependencies: "@types/yargs-parser" "*" -"@typescript-eslint/eslint-plugin@4.28.0": - version "4.28.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.28.0.tgz#1a66f03b264844387beb7dc85e1f1d403bd1803f" - integrity sha512-KcF6p3zWhf1f8xO84tuBailV5cN92vhS+VT7UJsPzGBm9VnQqfI9AsiMUFUCYHTYPg1uCCo+HyiDnpDuvkAMfQ== +"@typescript-eslint/eslint-plugin@4.29.2": + version "4.29.2" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.29.2.tgz#f54dc0a32b8f61c6024ab8755da05363b733838d" + integrity sha512-x4EMgn4BTfVd9+Z+r+6rmWxoAzBaapt4QFqE+d8L8sUtYZYLDTK6VG/y/SMMWA5t1/BVU5Kf+20rX4PtWzUYZg== dependencies: - "@typescript-eslint/experimental-utils" "4.28.0" - "@typescript-eslint/scope-manager" "4.28.0" + "@typescript-eslint/experimental-utils" "4.29.2" + "@typescript-eslint/scope-manager" "4.29.2" debug "^4.3.1" functional-red-black-tree "^1.0.1" regexpp "^3.1.0" @@ -2103,18 +2323,6 @@ semver "^7.3.5" tsutils "^3.21.0" -"@typescript-eslint/experimental-utils@4.28.0": - version "4.28.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-4.28.0.tgz#13167ed991320684bdc23588135ae62115b30ee0" - integrity sha512-9XD9s7mt3QWMk82GoyUpc/Ji03vz4T5AYlHF9DcoFNfJ/y3UAclRsfGiE2gLfXtyC+JRA3trR7cR296TEb1oiQ== - dependencies: - "@types/json-schema" "^7.0.7" - "@typescript-eslint/scope-manager" "4.28.0" - "@typescript-eslint/types" "4.28.0" - "@typescript-eslint/typescript-estree" "4.28.0" - eslint-scope "^5.1.1" - eslint-utils "^3.0.0" - "@typescript-eslint/experimental-utils@4.28.5": version "4.28.5" resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-4.28.5.tgz#66c28bef115b417cf9d80812a713e0e46bb42a64" @@ -2127,14 +2335,26 @@ eslint-scope "^5.1.1" eslint-utils "^3.0.0" -"@typescript-eslint/parser@4.28.0": - version "4.28.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-4.28.0.tgz#2404c16751a28616ef3abab77c8e51d680a12caa" - integrity sha512-7x4D22oPY8fDaOCvkuXtYYTQ6mTMmkivwEzS+7iml9F9VkHGbbZ3x4fHRwxAb5KeuSkLqfnYjs46tGx2Nour4A== +"@typescript-eslint/experimental-utils@4.29.2": + version "4.29.2" + resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-4.29.2.tgz#5f67fb5c5757ef2cb3be64817468ba35c9d4e3b7" + integrity sha512-P6mn4pqObhftBBPAv4GQtEK7Yos1fz/MlpT7+YjH9fTxZcALbiiPKuSIfYP/j13CeOjfq8/fr9Thr2glM9ub7A== + dependencies: + "@types/json-schema" "^7.0.7" + "@typescript-eslint/scope-manager" "4.29.2" + "@typescript-eslint/types" "4.29.2" + "@typescript-eslint/typescript-estree" "4.29.2" + eslint-scope "^5.1.1" + eslint-utils "^3.0.0" + +"@typescript-eslint/parser@4.29.2": + version "4.29.2" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-4.29.2.tgz#1c7744f4c27aeb74610c955d3dce9250e95c370a" + integrity sha512-WQ6BPf+lNuwteUuyk1jD/aHKqMQ9jrdCn7Gxt9vvBnzbpj7aWEf+aZsJ1zvTjx5zFxGCt000lsbD9tQPEL8u6g== dependencies: - "@typescript-eslint/scope-manager" "4.28.0" - "@typescript-eslint/types" "4.28.0" - "@typescript-eslint/typescript-estree" "4.28.0" + "@typescript-eslint/scope-manager" "4.29.2" + "@typescript-eslint/types" "4.29.2" + "@typescript-eslint/typescript-estree" "4.29.2" debug "^4.3.1" "@typescript-eslint/parser@^4.28.5": @@ -2147,14 +2367,6 @@ "@typescript-eslint/typescript-estree" "4.28.5" debug "^4.3.1" -"@typescript-eslint/scope-manager@4.28.0": - version "4.28.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-4.28.0.tgz#6a3009d2ab64a30fc8a1e257a1a320067f36a0ce" - integrity sha512-eCALCeScs5P/EYjwo6se9bdjtrh8ByWjtHzOkC4Tia6QQWtQr3PHovxh3TdYTuFcurkYI4rmFsRFpucADIkseg== - dependencies: - "@typescript-eslint/types" "4.28.0" - "@typescript-eslint/visitor-keys" "4.28.0" - "@typescript-eslint/scope-manager@4.28.5": version "4.28.5" resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-4.28.5.tgz#3a1b70c50c1535ac33322786ea99ebe403d3b923" @@ -2163,33 +2375,28 @@ "@typescript-eslint/types" "4.28.5" "@typescript-eslint/visitor-keys" "4.28.5" +"@typescript-eslint/scope-manager@4.29.2": + version "4.29.2" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-4.29.2.tgz#442b0f029d981fa402942715b1718ac7fcd5aa1b" + integrity sha512-mfHmvlQxmfkU8D55CkZO2sQOueTxLqGvzV+mG6S/6fIunDiD2ouwsAoiYCZYDDK73QCibYjIZmGhpvKwAB5BOA== + dependencies: + "@typescript-eslint/types" "4.29.2" + "@typescript-eslint/visitor-keys" "4.29.2" + "@typescript-eslint/types@4.27.0": version "4.27.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-4.27.0.tgz#712b408519ed699baff69086bc59cd2fc13df8d8" integrity sha512-I4ps3SCPFCKclRcvnsVA/7sWzh7naaM/b4pBO2hVxnM3wrU51Lveybdw5WoIktU/V4KfXrTt94V9b065b/0+wA== -"@typescript-eslint/types@4.28.0": - version "4.28.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-4.28.0.tgz#a33504e1ce7ac51fc39035f5fe6f15079d4dafb0" - integrity sha512-p16xMNKKoiJCVZY5PW/AfILw2xe1LfruTcfAKBj3a+wgNYP5I9ZEKNDOItoRt53p4EiPV6iRSICy8EPanG9ZVA== - "@typescript-eslint/types@4.28.5": version "4.28.5" resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-4.28.5.tgz#d33edf8e429f0c0930a7c3d44e9b010354c422e9" integrity sha512-MruOu4ZaDOLOhw4f/6iudyks/obuvvZUAHBDSW80Trnc5+ovmViLT2ZMDXhUV66ozcl6z0LJfKs1Usldgi/WCA== -"@typescript-eslint/typescript-estree@4.28.0": - version "4.28.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-4.28.0.tgz#e66d4e5aa2ede66fec8af434898fe61af10c71cf" - integrity sha512-m19UQTRtxMzKAm8QxfKpvh6OwQSXaW1CdZPoCaQuLwAq7VZMNuhJmZR4g5281s2ECt658sldnJfdpSZZaxUGMQ== - dependencies: - "@typescript-eslint/types" "4.28.0" - "@typescript-eslint/visitor-keys" "4.28.0" - debug "^4.3.1" - globby "^11.0.3" - is-glob "^4.0.1" - semver "^7.3.5" - tsutils "^3.21.0" +"@typescript-eslint/types@4.29.2": + version "4.29.2" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-4.29.2.tgz#fc0489c6b89773f99109fb0aa0aaddff21f52fcd" + integrity sha512-K6ApnEXId+WTGxqnda8z4LhNMa/pZmbTFkDxEBLQAbhLZL50DjeY0VIDCml/0Y3FlcbqXZrABqrcKxq+n0LwzQ== "@typescript-eslint/typescript-estree@4.28.5": version "4.28.5" @@ -2204,6 +2411,19 @@ semver "^7.3.5" tsutils "^3.21.0" +"@typescript-eslint/typescript-estree@4.29.2": + version "4.29.2" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-4.29.2.tgz#a0ea8b98b274adbb2577100ba545ddf8bf7dc219" + integrity sha512-TJ0/hEnYxapYn9SGn3dCnETO0r+MjaxtlWZ2xU+EvytF0g4CqTpZL48SqSNn2hXsPolnewF30pdzR9a5Lj3DNg== + dependencies: + "@typescript-eslint/types" "4.29.2" + "@typescript-eslint/visitor-keys" "4.29.2" + debug "^4.3.1" + globby "^11.0.3" + is-glob "^4.0.1" + semver "^7.3.5" + tsutils "^3.21.0" + "@typescript-eslint/typescript-estree@^4.8.2": version "4.27.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-4.27.0.tgz#189a7b9f1d0717d5cccdcc17247692dedf7a09da" @@ -2225,14 +2445,6 @@ "@typescript-eslint/types" "4.27.0" eslint-visitor-keys "^2.0.0" -"@typescript-eslint/visitor-keys@4.28.0": - version "4.28.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-4.28.0.tgz#255c67c966ec294104169a6939d96f91c8a89434" - integrity sha512-PjJyTWwrlrvM5jazxYF5ZPs/nl0kHDZMVbuIcbpawVXaDPelp3+S9zpOz5RmVUfS/fD5l5+ZXNKnWhNYjPzCvw== - dependencies: - "@typescript-eslint/types" "4.28.0" - eslint-visitor-keys "^2.0.0" - "@typescript-eslint/visitor-keys@4.28.5": version "4.28.5" resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-4.28.5.tgz#ffee2c602762ed6893405ee7c1144d9cc0a29675" @@ -2241,6 +2453,14 @@ "@typescript-eslint/types" "4.28.5" eslint-visitor-keys "^2.0.0" +"@typescript-eslint/visitor-keys@4.29.2": + version "4.29.2" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-4.29.2.tgz#d2da7341f3519486f50655159f4e5ecdcb2cd1df" + integrity sha512-bDgJLQ86oWHJoZ1ai4TZdgXzJxsea3Ee9u9wsTAvjChdj2WLcVsgWYAPeY7RQMn16tKrlQaBnpKv7KBfs4EQag== + dependencies: + "@typescript-eslint/types" "4.29.2" + eslint-visitor-keys "^2.0.0" + "@ungap/promise-all-settled@1.1.2": version "1.1.2" resolved "https://registry.yarnpkg.com/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz#aa58042711d6e3275dd37dc597e5d31e8c290a44" @@ -2606,16 +2826,16 @@ resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.11.0.tgz#d61f46d83b2519250e2784daf5b09479a8b41c59" integrity sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA== -babel-jest@^27.0.5: - version "27.0.5" - resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-27.0.5.tgz#cd34c033ada05d1362211e5152391fd7a88080c8" - integrity sha512-bTMAbpCX7ldtfbca2llYLeSFsDM257aspyAOpsdrdSrBqoLkWCy4HPYTXtXWaSLgFPjrJGACL65rzzr4RFGadw== +babel-jest@^27.0.6: + version "27.0.6" + resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-27.0.6.tgz#e99c6e0577da2655118e3608b68761a5a69bd0d8" + integrity sha512-iTJyYLNc4wRofASmofpOc5NK9QunwMk+TLFgGXsTFS8uEqmd8wdI7sga0FPe2oVH3b5Agt/EAK1QjPEuKL8VfA== dependencies: - "@jest/transform" "^27.0.5" - "@jest/types" "^27.0.2" + "@jest/transform" "^27.0.6" + "@jest/types" "^27.0.6" "@types/babel__core" "^7.1.14" babel-plugin-istanbul "^6.0.0" - babel-preset-jest "^27.0.1" + babel-preset-jest "^27.0.6" chalk "^4.0.0" graceful-fs "^4.2.4" slash "^3.0.0" @@ -2638,10 +2858,10 @@ istanbul-lib-instrument "^4.0.0" test-exclude "^6.0.0" -babel-plugin-jest-hoist@^27.0.1: - version "27.0.1" - resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-27.0.1.tgz#a6d10e484c93abff0f4e95f437dad26e5736ea11" - integrity sha512-sqBF0owAcCDBVEDtxqfYr2F36eSHdx7lAVGyYuOBRnKdD6gzcy0I0XrAYCZgOA3CRrLhmR+Uae9nogPzmAtOfQ== +babel-plugin-jest-hoist@^27.0.6: + version "27.0.6" + resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-27.0.6.tgz#f7c6b3d764af21cb4a2a1ab6870117dbde15b456" + integrity sha512-CewFeM9Vv2gM7Yr9n5eyyLVPRSiBnk6lKZRjgwYnGKSl9M14TMn2vkN02wTF04OGuSDLEzlWiMzvjXuW9mB6Gw== dependencies: "@babel/template" "^7.3.3" "@babel/types" "^7.3.3" @@ -2688,10 +2908,10 @@ dependencies: "@babel/helper-define-polyfill-provider" "^0.2.2" -babel-plugin-styled-components@^1.12.0: - version "1.12.0" - resolved "https://registry.yarnpkg.com/babel-plugin-styled-components/-/babel-plugin-styled-components-1.12.0.tgz#1dec1676512177de6b827211e9eda5a30db4f9b9" - integrity sha512-FEiD7l5ZABdJPpLssKXjBUJMYqzbcNzBowfXDCdJhOpbhWiewapUaY+LZGT8R4Jg2TwOjGjG4RKeyrO5p9sBkA== +babel-plugin-styled-components@^1.13.2: + version "1.13.2" + resolved "https://registry.yarnpkg.com/babel-plugin-styled-components/-/babel-plugin-styled-components-1.13.2.tgz#ebe0e6deff51d7f93fceda1819e9b96aeb88278d" + integrity sha512-Vb1R3d4g+MUfPQPVDMCGjm3cDocJEUTR7Xq7QS95JWWeksN1wdFRYpD2kulDgI3Huuaf1CZd+NK4KQmqUFh5dA== dependencies: "@babel/helper-annotate-as-pure" "^7.0.0" "@babel/helper-module-imports" "^7.0.0" @@ -2721,12 +2941,12 @@ "@babel/plugin-syntax-optional-chaining" "^7.8.3" "@babel/plugin-syntax-top-level-await" "^7.8.3" -babel-preset-jest@^27.0.1: - version "27.0.1" - resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-27.0.1.tgz#7a50c75d16647c23a2cf5158d5bb9eb206b10e20" - integrity sha512-nIBIqCEpuiyhvjQs2mVNwTxQQa2xk70p9Dd/0obQGBf8FBzbnI8QhQKzLsWMN2i6q+5B0OcWDtrboBX5gmOLyA== +babel-preset-jest@^27.0.6: + version "27.0.6" + resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-27.0.6.tgz#909ef08e9f24a4679768be2f60a3df0856843f9d" + integrity sha512-WObA0/Biw2LrVVwZkF/2GqbOdzhKD6Fkdwhoy9ASIrOWr/zodcSpQh72JOkEn6NWyjmnPDjNSqaGN4KnpKzhXw== dependencies: - babel-plugin-jest-hoist "^27.0.1" + babel-plugin-jest-hoist "^27.0.6" babel-preset-current-node-syntax "^1.0.0" balanced-match@^1.0.0: @@ -2966,6 +3186,17 @@ escalade "^3.1.1" node-releases "^1.1.71" +browserslist@^4.16.7: + version "4.16.7" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.16.7.tgz#108b0d1ef33c4af1b587c54f390e7041178e4335" + integrity sha512-7I4qVwqZltJ7j37wObBe3SoTz+nS8APaNcrBOlgoirb6/HbEU2XxW/LpUDTCngM6iauwFqmRTuOMfyKnFGY5JA== + dependencies: + caniuse-lite "^1.0.30001248" + colorette "^1.2.2" + electron-to-chromium "^1.3.793" + escalade "^3.1.1" + node-releases "^1.1.73" + bs58@^4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/bs58/-/bs58-4.0.1.tgz#be161e76c354f6f788ae4071f63f34e8c4f0a42a" @@ -3024,6 +3255,11 @@ resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f" integrity sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8= +builtin-modules@^3.1.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-3.2.0.tgz#45d5db99e7ee5e6bc4f362e008bf917ab5049887" + integrity sha512-lGzLKcioL90C7wMczpkY0n/oART3MbBa8R9OFGE1rJxoVI86u4WAGfEk8Wjv10eKSyTHVGkSo3bvBylCEtk7LA== + bytes@3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.0.tgz#f6cf7933a360e0588fa9fde85651cdc7f805d1f6" @@ -3085,6 +3321,11 @@ resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001238.tgz#e6a8b45455c5de601718736d0242feef0ecdda15" integrity sha512-bZGam2MxEt7YNsa2VwshqWQMwrYs5tR5WZQRYSuFxsBQunWjBuXhN4cS9nV5FFb1Z9y+DoQcQ0COyQbv6A+CKw== +caniuse-lite@^1.0.30001248: + version "1.0.30001251" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001251.tgz#6853a606ec50893115db660f82c094d18f096d85" + integrity sha512-HOe1r+9VkU4TFmnU70z+r7OLmtR+/chB1rdcJUeQlAinjEeb0cKL20tlAtOagNZhbrtLnCvV19B4FmF1rgzl6A== + caseless@~0.12.0: version "0.12.0" resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" @@ -3134,6 +3375,14 @@ ansi-styles "^4.1.0" supports-color "^7.1.0" +chalk@^4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" + integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + changelog-parser@^2.0.0: version "2.8.0" resolved "https://registry.yarnpkg.com/changelog-parser/-/changelog-parser-2.8.0.tgz#c14293e3e8fab797913c722de965480198650108" @@ -3472,12 +3721,12 @@ browserslist "^4.16.6" semver "7.0.0" -core-js-compat@^3.15.0: - version "3.15.1" - resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.15.1.tgz#1afe233716d37ee021956ef097594071b2b585a7" - integrity sha512-xGhzYMX6y7oEGQGAJmP2TmtBLvR4nZmRGEcFa3ubHOq5YEp51gGN9AovVa0AoujGZIq+Wm6dISiYyGNfdflYww== +core-js-compat@^3.16.0: + version "3.16.1" + resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.16.1.tgz#c44b7caa2dcb94b673a98f27eee1c8312f55bc2d" + integrity sha512-NHXQXvRbd4nxp9TEmooTJLUf94ySUG6+DSsscBpTftN1lQLQ4LjnWvc7AoIo4UjDsFF3hB8Uh5LLCRRdaiT5MQ== dependencies: - browserslist "^4.16.6" + browserslist "^4.16.7" semver "7.0.0" core-util-is@1.0.2, core-util-is@~1.0.0: @@ -3493,10 +3742,10 @@ object-assign "^4" vary "^1" -coveralls@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/coveralls/-/coveralls-3.1.0.tgz#13c754d5e7a2dd8b44fe5269e21ca394fb4d615b" - integrity sha512-sHxOu2ELzW8/NC1UP5XVLbZDzO4S3VxfFye3XYCznopHy02YjNkHcj5bKaVw2O7hVaBdBjEdQGpie4II1mWhuQ== +coveralls@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/coveralls/-/coveralls-3.1.1.tgz#f5d4431d8b5ae69c5079c8f8ca00d64ac77cf081" + integrity sha512-+dxnG2NHncSD1NrqbSM3dn/lE57O6Qf/koe9+I7c+wzkqRmEvcp0kgJdxKInzYzkICKkFMZsX3Vct3++tsF9ww== dependencies: js-yaml "^3.13.1" lcov-parse "^1.0.0" @@ -3883,10 +4132,10 @@ node-source-walk "^4.2.0" typescript "^3.9.7" -diff-sequences@^27.0.1: - version "27.0.1" - resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-27.0.1.tgz#9c9801d52ed5f576ff0a20e3022a13ee6e297e7c" - integrity sha512-XPLijkfJUh/PIBnfkcSHgvD6tlYixmcMAn3osTk6jt+H0v/mgURto1XUiD9DKuGX5NDoVS6dSlA23gd9FUaCFg== +diff-sequences@^27.0.6: + version "27.0.6" + resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-27.0.6.tgz#3305cb2e55a033924054695cc66019fd7f8e5723" + integrity sha512-ag6wfpBFyNXZ0p8pcuIDS//D8H062ZQJ3fzYxjpmeKjnz8W4pekL3AI8VohmyZmsWW2PWaHgjsmqR6L13101VQ== diff@5.0.0: version "5.0.0" @@ -3970,6 +4219,13 @@ jsbn "~0.1.0" safer-buffer "^2.1.0" +ed2curve@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/ed2curve/-/ed2curve-0.3.0.tgz#322b575152a45305429d546b071823a93129a05d" + integrity sha512-8w2fmmq3hv9rCrcI7g9hms2pMunQr1JINfcjwR9tAyZqhtyaMN991lF/ZfHfr5tzZQ8c7y7aBgZbjfbd0fjFwQ== + dependencies: + tweetnacl "1.x.x" + ee-first@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" @@ -3980,6 +4236,11 @@ resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.752.tgz#0728587f1b9b970ec9ffad932496429aef750d09" integrity sha512-2Tg+7jSl3oPxgsBsWKh5H83QazTkmWG/cnNwJplmyZc7KcN61+I10oUgaXSVk/NwfvN3BdkKDR4FYuRBQQ2v0A== +electron-to-chromium@^1.3.793: + version "1.3.807" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.807.tgz#c2eb803f4f094869b1a24151184ffbbdbf688b1f" + integrity sha512-p8uxxg2a23zRsvQ2uwA/OOI+O4BQxzaR7YKMIGGGQCpYmkFX2CVF5f0/hxLMV7yCr7nnJViCwHLhPfs52rIYCA== + elliptic@6.5.4, elliptic@^6.4.0, elliptic@^6.5.2, elliptic@^6.5.3, elliptic@^6.5.4: version "6.5.4" resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.4.tgz#da37cebd31e79a1367e941b592ed1fbebd58abbb" @@ -4151,18 +4412,18 @@ resolved "https://registry.yarnpkg.com/eslint-config-standard/-/eslint-config-standard-16.0.3.tgz#6c8761e544e96c531ff92642eeb87842b8488516" integrity sha512-x4fmJL5hGqNJKGHSjnLdgA6U6h1YW/G2dW9fA+cyVur4SK6lyue8+UgNKWlZtUDTXvgKDD/Oa3GQjmB5kjtVvg== -eslint-import-resolver-node@^0.3.4: - version "0.3.4" - resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.4.tgz#85ffa81942c25012d8231096ddf679c03042c717" - integrity sha512-ogtf+5AB/O+nM6DIeBUNr2fuT7ot9Qg/1harBfBtaP13ekEWFQEEMP94BCB7zaNW3gyY+8SHYF00rnqYwXKWOA== +eslint-import-resolver-node@^0.3.5, eslint-import-resolver-node@^0.3.6: + version "0.3.6" + resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.6.tgz#4048b958395da89668252001dbd9eca6b83bacbd" + integrity sha512-0En0w03NRVMn9Uiyn8YRPDKvWjxCWkslUEhGNTdGx15RvPJYQ+lbOlqrlNI2vEAs4pDYK4f/HN2TbDmk5TP0iw== dependencies: - debug "^2.6.9" - resolve "^1.13.1" + debug "^3.2.7" + resolve "^1.20.0" -eslint-module-utils@^2.6.1: - version "2.6.1" - resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.6.1.tgz#b51be1e473dd0de1c5ea638e22429c2490ea8233" - integrity sha512-ZXI9B8cxAJIH4nfkhTwcRTEAnrVfobYqwjWy/QMCZ8rHkZHFjf9yO4BzpiF9kCSfNlMG54eKigISHpX0+AaT4A== +eslint-module-utils@^2.6.2: + version "2.6.2" + resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.6.2.tgz#94e5540dd15fe1522e8ffa3ec8db3b7fa7e7a534" + integrity sha512-QG8pcgThYOuqxupd06oYTZoNOGaUdTY1PqK+oS6ElF6vs4pBdk/aYxFVQQXzcrAqp9m7cl7lb2ubazX+g16k2Q== dependencies: debug "^3.2.7" pkg-dir "^2.0.0" @@ -4180,17 +4441,22 @@ resolved "https://registry.yarnpkg.com/eslint-plugin-header/-/eslint-plugin-header-3.1.1.tgz#6ce512432d57675265fac47292b50d1eff11acd6" integrity sha512-9vlKxuJ4qf793CmeeSrZUvVClw6amtpghq3CuWcB5cUNnWHQhgcqy5eF8oVKFk1G3Y/CbchGfEaw3wiIJaNmVg== -eslint-plugin-import@^2.23.4: - version "2.23.4" - resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.23.4.tgz#8dceb1ed6b73e46e50ec9a5bb2411b645e7d3d97" - integrity sha512-6/wP8zZRsnQFiR3iaPFgh5ImVRM1WN5NUWfTIRqwOdeiGJlBcSk82o1FEVq8yXmy4lkIzTo7YhHCIxlU/2HyEQ== +eslint-plugin-import-newlines@^1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/eslint-plugin-import-newlines/-/eslint-plugin-import-newlines-1.1.4.tgz#d69d03fe512b2f54bc781d1dfc51a4ad99df7a52" + integrity sha512-GCIM+524XQOFcEPinEyrvktQHkQq+k+kYCwbRrIioGBVGnk3RGDFWv5BPqBQCDci6SNZCVgIOi3/FmtDetbxvA== + +eslint-plugin-import@^2.24.0: + version "2.24.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.24.0.tgz#697ffd263e24da5e84e03b282f5fb62251777177" + integrity sha512-Kc6xqT9hiYi2cgybOc0I2vC9OgAYga5o/rAFinam/yF/t5uBqxQbauNPMC6fgb640T/89P0gFoO27FOilJ/Cqg== dependencies: array-includes "^3.1.3" array.prototype.flat "^1.2.4" debug "^2.6.9" doctrine "^2.1.0" - eslint-import-resolver-node "^0.3.4" - eslint-module-utils "^2.6.1" + eslint-import-resolver-node "^0.3.5" + eslint-module-utils "^2.6.2" find-up "^2.0.0" has "^1.0.3" is-core-module "^2.4.0" @@ -4285,13 +4551,14 @@ resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz#f65328259305927392c938ed44eb0a5c9b2bd303" integrity sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw== -eslint@^7.29.0: - version "7.29.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.29.0.tgz#ee2a7648f2e729485e4d0bd6383ec1deabc8b3c0" - integrity sha512-82G/JToB9qIy/ArBzIWG9xvvwL3R86AlCjtGw+A29OMZDqhTybz/MByORSukGxeI+YPCR4coYyITKk8BFH9nDA== +eslint@^7.31.0: + version "7.31.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.31.0.tgz#f972b539424bf2604907a970860732c5d99d3aca" + integrity sha512-vafgJpSh2ia8tnTkNUkwxGmnumgckLh5aAbLa1xRmIn9+owi8qBNGKL+B881kNKNTy7FFqTEkpNkUvmw0n6PkA== dependencies: "@babel/code-frame" "7.12.11" - "@eslint/eslintrc" "^0.4.2" + "@eslint/eslintrc" "^0.4.3" + "@humanwhocodes/config-array" "^0.5.0" ajv "^6.10.0" chalk "^4.0.0" cross-spawn "^7.0.2" @@ -4330,10 +4597,10 @@ text-table "^0.2.0" v8-compile-cache "^2.0.3" -eslint@^7.31.0: - version "7.31.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.31.0.tgz#f972b539424bf2604907a970860732c5d99d3aca" - integrity sha512-vafgJpSh2ia8tnTkNUkwxGmnumgckLh5aAbLa1xRmIn9+owi8qBNGKL+B881kNKNTy7FFqTEkpNkUvmw0n6PkA== +eslint@^7.32.0: + version "7.32.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.32.0.tgz#c6d328a14be3fb08c8d1d21e12c02fdb7a2a812d" + integrity sha512-VHZ8gX+EDfz+97jGcgyGCyRia/dPOd6Xh9yPv8Bl1+SoaIwD+a/vlrOmGRUyOYu7MwUhc7CxqeaDZU13S4+EpA== dependencies: "@babel/code-frame" "7.12.11" "@eslint/eslintrc" "^0.4.3" @@ -4414,6 +4681,16 @@ resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.2.0.tgz#307df42547e6cc7324d3cf03c155d5cdb8c53880" integrity sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ== +estree-walker@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-1.0.1.tgz#31bc5d612c96b704106b477e6dd5d8aa138cb700" + integrity sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg== + +estree-walker@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-2.0.2.tgz#52f010178c2a4c117a7757cfe942adb7d2da4cac" + integrity sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w== + esutils@^2.0.2: version "2.0.3" resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" @@ -4574,17 +4851,17 @@ snapdragon "^0.8.1" to-regex "^3.0.1" -expect@^27.0.2: - version "27.0.2" - resolved "https://registry.yarnpkg.com/expect/-/expect-27.0.2.tgz#e66ca3a4c9592f1c019fa1d46459a9d2084f3422" - integrity sha512-YJFNJe2+P2DqH+ZrXy+ydRQYO87oxRUonZImpDodR1G7qo3NYd3pL+NQ9Keqpez3cehczYwZDBC3A7xk3n7M/w== +expect@^27.0.6: + version "27.0.6" + resolved "https://registry.yarnpkg.com/expect/-/expect-27.0.6.tgz#a4d74fbe27222c718fff68ef49d78e26a8fd4c05" + integrity sha512-psNLt8j2kwg42jGBDSfAlU49CEZxejN1f1PlANWDZqIhBOVU/c2Pm888FcjWJzFewhIsNWfZJeLjUjtKGiPuSw== dependencies: - "@jest/types" "^27.0.2" + "@jest/types" "^27.0.6" ansi-styles "^5.0.0" - jest-get-type "^27.0.1" - jest-matcher-utils "^27.0.2" - jest-message-util "^27.0.2" - jest-regex-util "^27.0.1" + jest-get-type "^27.0.6" + jest-matcher-utils "^27.0.6" + jest-message-util "^27.0.6" + jest-regex-util "^27.0.6" express@^4.14.0: version "4.17.1" @@ -5857,6 +6134,11 @@ resolved "https://registry.yarnpkg.com/is-interactive/-/is-interactive-1.0.0.tgz#cea6e6ae5c870a7b0a0004070b7b587e0252912e" integrity sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w== +is-module@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-module/-/is-module-1.0.0.tgz#3258fb69f78c14d5b815d664336b4cffb6441591" + integrity sha1-Mlj7afeMFNW4FdZkM2tM/7ZEFZE= + is-negative-zero@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.1.tgz#3de746c18dda2319241a53675908d8f766f11c24" @@ -5931,6 +6213,13 @@ resolved "https://registry.yarnpkg.com/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz#171ed6f19e3ac554394edf78caa05784a45bebb5" integrity sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ== +is-reference@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/is-reference/-/is-reference-1.2.1.tgz#8b2dac0b371f4bc994fdeaba9eb542d03002d0b7" + integrity sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ== + dependencies: + "@types/estree" "*" + is-regex@^1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.3.tgz#d029f9aff6448b93ebbe3f33dac71511fdcbef9f" @@ -6088,226 +6377,226 @@ has-to-string-tag-x "^1.2.0" is-object "^1.0.1" -jest-changed-files@^27.0.2: - version "27.0.2" - resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-27.0.2.tgz#997253042b4a032950fc5f56abf3c5d1f8560801" - integrity sha512-eMeb1Pn7w7x3wue5/vF73LPCJ7DKQuC9wQUR5ebP9hDPpk5hzcT/3Hmz3Q5BOFpR3tgbmaWhJcMTVgC8Z1NuMw== +jest-changed-files@^27.0.6: + version "27.0.6" + resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-27.0.6.tgz#bed6183fcdea8a285482e3b50a9a7712d49a7a8b" + integrity sha512-BuL/ZDauaq5dumYh5y20sn4IISnf1P9A0TDswTxUi84ORGtVa86ApuBHqICL0vepqAnZiY6a7xeSPWv2/yy4eA== dependencies: - "@jest/types" "^27.0.2" + "@jest/types" "^27.0.6" execa "^5.0.0" throat "^6.0.1" -jest-circus@^27.0.5: - version "27.0.5" - resolved "https://registry.yarnpkg.com/jest-circus/-/jest-circus-27.0.5.tgz#b5e327f1d6857c8485126f8e364aefa4378debaa" - integrity sha512-p5rO90o1RTh8LPOG6l0Fc9qgp5YGv+8M5CFixhMh7gGHtGSobD1AxX9cjFZujILgY8t30QZ7WVvxlnuG31r8TA== +jest-circus@^27.0.6: + version "27.0.6" + resolved "https://registry.yarnpkg.com/jest-circus/-/jest-circus-27.0.6.tgz#dd4df17c4697db6a2c232aaad4e9cec666926668" + integrity sha512-OJlsz6BBeX9qR+7O9lXefWoc2m9ZqcZ5Ohlzz0pTEAG4xMiZUJoacY8f4YDHxgk0oKYxj277AfOk9w6hZYvi1Q== dependencies: - "@jest/environment" "^27.0.5" - "@jest/test-result" "^27.0.2" - "@jest/types" "^27.0.2" + "@jest/environment" "^27.0.6" + "@jest/test-result" "^27.0.6" + "@jest/types" "^27.0.6" "@types/node" "*" chalk "^4.0.0" co "^4.6.0" dedent "^0.7.0" - expect "^27.0.2" + expect "^27.0.6" is-generator-fn "^2.0.0" - jest-each "^27.0.2" - jest-matcher-utils "^27.0.2" - jest-message-util "^27.0.2" - jest-runtime "^27.0.5" - jest-snapshot "^27.0.5" - jest-util "^27.0.2" - pretty-format "^27.0.2" + jest-each "^27.0.6" + jest-matcher-utils "^27.0.6" + jest-message-util "^27.0.6" + jest-runtime "^27.0.6" + jest-snapshot "^27.0.6" + jest-util "^27.0.6" + pretty-format "^27.0.6" slash "^3.0.0" stack-utils "^2.0.3" throat "^6.0.1" -jest-cli@^27.0.5: - version "27.0.5" - resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-27.0.5.tgz#f359ba042624cffb96b713010a94bffb7498a37c" - integrity sha512-kZqY020QFOFQKVE2knFHirTBElw3/Q0kUbDc3nMfy/x+RQ7zUY89SUuzpHHJoSX1kX7Lq569ncvjNqU3Td/FCA== +jest-cli@^27.0.6: + version "27.0.6" + resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-27.0.6.tgz#d021e5f4d86d6a212450d4c7b86cb219f1e6864f" + integrity sha512-qUUVlGb9fdKir3RDE+B10ULI+LQrz+MCflEH2UJyoUjoHHCbxDrMxSzjQAPUMsic4SncI62ofYCcAvW6+6rhhg== dependencies: - "@jest/core" "^27.0.5" - "@jest/test-result" "^27.0.2" - "@jest/types" "^27.0.2" + "@jest/core" "^27.0.6" + "@jest/test-result" "^27.0.6" + "@jest/types" "^27.0.6" chalk "^4.0.0" exit "^0.1.2" graceful-fs "^4.2.4" import-local "^3.0.2" - jest-config "^27.0.5" - jest-util "^27.0.2" - jest-validate "^27.0.2" + jest-config "^27.0.6" + jest-util "^27.0.6" + jest-validate "^27.0.6" prompts "^2.0.1" yargs "^16.0.3" -jest-config@^27.0.5: - version "27.0.5" - resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-27.0.5.tgz#683da3b0d8237675c29c817f6e3aba1481028e19" - integrity sha512-zCUIXag7QIXKEVN4kUKbDBDi9Q53dV5o3eNhGqe+5zAbt1vLs4VE3ceWaYrOub0L4Y7E9pGfM84TX/0ARcE+Qw== +jest-config@^27.0.6: + version "27.0.6" + resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-27.0.6.tgz#119fb10f149ba63d9c50621baa4f1f179500277f" + integrity sha512-JZRR3I1Plr2YxPBhgqRspDE2S5zprbga3swYNrvY3HfQGu7p/GjyLOqwrYad97tX3U3mzT53TPHVmozacfP/3w== dependencies: "@babel/core" "^7.1.0" - "@jest/test-sequencer" "^27.0.5" - "@jest/types" "^27.0.2" - babel-jest "^27.0.5" + "@jest/test-sequencer" "^27.0.6" + "@jest/types" "^27.0.6" + babel-jest "^27.0.6" chalk "^4.0.0" deepmerge "^4.2.2" glob "^7.1.1" graceful-fs "^4.2.4" is-ci "^3.0.0" - jest-circus "^27.0.5" - jest-environment-jsdom "^27.0.5" - jest-environment-node "^27.0.5" - jest-get-type "^27.0.1" - jest-jasmine2 "^27.0.5" - jest-regex-util "^27.0.1" - jest-resolve "^27.0.5" - jest-runner "^27.0.5" - jest-util "^27.0.2" - jest-validate "^27.0.2" + jest-circus "^27.0.6" + jest-environment-jsdom "^27.0.6" + jest-environment-node "^27.0.6" + jest-get-type "^27.0.6" + jest-jasmine2 "^27.0.6" + jest-regex-util "^27.0.6" + jest-resolve "^27.0.6" + jest-runner "^27.0.6" + jest-util "^27.0.6" + jest-validate "^27.0.6" micromatch "^4.0.4" - pretty-format "^27.0.2" + pretty-format "^27.0.6" -jest-diff@^27.0.2: - version "27.0.2" - resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-27.0.2.tgz#f315b87cee5dc134cf42c2708ab27375cc3f5a7e" - integrity sha512-BFIdRb0LqfV1hBt8crQmw6gGQHVDhM87SpMIZ45FPYKReZYG5er1+5pIn2zKqvrJp6WNox0ylR8571Iwk2Dmgw== +jest-diff@^27.0.6: + version "27.0.6" + resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-27.0.6.tgz#4a7a19ee6f04ad70e0e3388f35829394a44c7b5e" + integrity sha512-Z1mqgkTCSYaFgwTlP/NUiRzdqgxmmhzHY1Tq17zL94morOHfHu3K4bgSgl+CR4GLhpV8VxkuOYuIWnQ9LnFqmg== dependencies: chalk "^4.0.0" - diff-sequences "^27.0.1" - jest-get-type "^27.0.1" - pretty-format "^27.0.2" + diff-sequences "^27.0.6" + jest-get-type "^27.0.6" + pretty-format "^27.0.6" -jest-docblock@^27.0.1: - version "27.0.1" - resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-27.0.1.tgz#bd9752819b49fa4fab1a50b73eb58c653b962e8b" - integrity sha512-TA4+21s3oebURc7VgFV4r7ltdIJ5rtBH1E3Tbovcg7AV+oLfD5DcJ2V2vJ5zFA9sL5CFd/d2D6IpsAeSheEdrA== +jest-docblock@^27.0.6: + version "27.0.6" + resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-27.0.6.tgz#cc78266acf7fe693ca462cbbda0ea4e639e4e5f3" + integrity sha512-Fid6dPcjwepTFraz0YxIMCi7dejjJ/KL9FBjPYhBp4Sv1Y9PdhImlKZqYU555BlN4TQKaTc+F2Av1z+anVyGkA== dependencies: detect-newline "^3.0.0" -jest-each@^27.0.2: - version "27.0.2" - resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-27.0.2.tgz#865ddb4367476ced752167926b656fa0dcecd8c7" - integrity sha512-OLMBZBZ6JkoXgUenDtseFRWA43wVl2BwmZYIWQws7eS7pqsIvePqj/jJmEnfq91ALk3LNphgwNK/PRFBYi7ITQ== +jest-each@^27.0.6: + version "27.0.6" + resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-27.0.6.tgz#cee117071b04060158dc8d9a66dc50ad40ef453b" + integrity sha512-m6yKcV3bkSWrUIjxkE9OC0mhBZZdhovIW5ergBYirqnkLXkyEn3oUUF/QZgyecA1cF1QFyTE8bRRl8Tfg1pfLA== dependencies: - "@jest/types" "^27.0.2" + "@jest/types" "^27.0.6" chalk "^4.0.0" - jest-get-type "^27.0.1" - jest-util "^27.0.2" - pretty-format "^27.0.2" + jest-get-type "^27.0.6" + jest-util "^27.0.6" + pretty-format "^27.0.6" -jest-environment-jsdom@^27.0.5: - version "27.0.5" - resolved "https://registry.yarnpkg.com/jest-environment-jsdom/-/jest-environment-jsdom-27.0.5.tgz#c36771977cf4490a9216a70473b39161d193c212" - integrity sha512-ToWhViIoTl5738oRaajTMgYhdQL73UWPoV4GqHGk2DPhs+olv8OLq5KoQW8Yf+HtRao52XLqPWvl46dPI88PdA== +jest-environment-jsdom@^27.0.6: + version "27.0.6" + resolved "https://registry.yarnpkg.com/jest-environment-jsdom/-/jest-environment-jsdom-27.0.6.tgz#f66426c4c9950807d0a9f209c590ce544f73291f" + integrity sha512-FvetXg7lnXL9+78H+xUAsra3IeZRTiegA3An01cWeXBspKXUhAwMM9ycIJ4yBaR0L7HkoMPaZsozCLHh4T8fuw== dependencies: - "@jest/environment" "^27.0.5" - "@jest/fake-timers" "^27.0.5" - "@jest/types" "^27.0.2" + "@jest/environment" "^27.0.6" + "@jest/fake-timers" "^27.0.6" + "@jest/types" "^27.0.6" "@types/node" "*" - jest-mock "^27.0.3" - jest-util "^27.0.2" + jest-mock "^27.0.6" + jest-util "^27.0.6" jsdom "^16.6.0" -jest-environment-node@^27.0.5: - version "27.0.5" - resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-27.0.5.tgz#b7238fc2b61ef2fb9563a3b7653a95fa009a6a54" - integrity sha512-47qqScV/WMVz5OKF5TWpAeQ1neZKqM3ySwNveEnLyd+yaE/KT6lSMx/0SOx60+ZUcVxPiESYS+Kt2JS9y4PpkQ== +jest-environment-node@^27.0.6: + version "27.0.6" + resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-27.0.6.tgz#a6699b7ceb52e8d68138b9808b0c404e505f3e07" + integrity sha512-+Vi6yLrPg/qC81jfXx3IBlVnDTI6kmRr08iVa2hFCWmJt4zha0XW7ucQltCAPhSR0FEKEoJ3i+W4E6T0s9is0w== dependencies: - "@jest/environment" "^27.0.5" - "@jest/fake-timers" "^27.0.5" - "@jest/types" "^27.0.2" + "@jest/environment" "^27.0.6" + "@jest/fake-timers" "^27.0.6" + "@jest/types" "^27.0.6" "@types/node" "*" - jest-mock "^27.0.3" - jest-util "^27.0.2" + jest-mock "^27.0.6" + jest-util "^27.0.6" -jest-get-type@^27.0.1: - version "27.0.1" - resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-27.0.1.tgz#34951e2b08c8801eb28559d7eb732b04bbcf7815" - integrity sha512-9Tggo9zZbu0sHKebiAijyt1NM77Z0uO4tuWOxUCujAiSeXv30Vb5D4xVF4UR4YWNapcftj+PbByU54lKD7/xMg== +jest-get-type@^27.0.6: + version "27.0.6" + resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-27.0.6.tgz#0eb5c7f755854279ce9b68a9f1a4122f69047cfe" + integrity sha512-XTkK5exIeUbbveehcSR8w0bhH+c0yloW/Wpl+9vZrjzztCPWrxhHwkIFpZzCt71oRBsgxmuUfxEqOYoZI2macg== -jest-haste-map@^27.0.5: - version "27.0.5" - resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-27.0.5.tgz#2e1e55073b5328410a2c0d74b334e513d71f3470" - integrity sha512-3LFryGSHxwPFHzKIs6W0BGA2xr6g1MvzSjR3h3D8K8Uqy4vbRm/grpGHzbPtIbOPLC6wFoViRrNEmd116QWSkw== +jest-haste-map@^27.0.6: + version "27.0.6" + resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-27.0.6.tgz#4683a4e68f6ecaa74231679dca237279562c8dc7" + integrity sha512-4ldjPXX9h8doB2JlRzg9oAZ2p6/GpQUNAeiYXqcpmrKbP0Qev0wdZlxSMOmz8mPOEnt4h6qIzXFLDi8RScX/1w== dependencies: - "@jest/types" "^27.0.2" + "@jest/types" "^27.0.6" "@types/graceful-fs" "^4.1.2" "@types/node" "*" anymatch "^3.0.3" fb-watchman "^2.0.0" graceful-fs "^4.2.4" - jest-regex-util "^27.0.1" - jest-serializer "^27.0.1" - jest-util "^27.0.2" - jest-worker "^27.0.2" + jest-regex-util "^27.0.6" + jest-serializer "^27.0.6" + jest-util "^27.0.6" + jest-worker "^27.0.6" micromatch "^4.0.4" walker "^1.0.7" optionalDependencies: fsevents "^2.3.2" -jest-jasmine2@^27.0.5: - version "27.0.5" - resolved "https://registry.yarnpkg.com/jest-jasmine2/-/jest-jasmine2-27.0.5.tgz#8a6eb2a685cdec3af13881145c77553e4e197776" - integrity sha512-m3TojR19sFmTn79QoaGy1nOHBcLvtLso6Zh7u+gYxZWGcza4rRPVqwk1hciA5ZOWWZIJOukAcore8JRX992FaA== +jest-jasmine2@^27.0.6: + version "27.0.6" + resolved "https://registry.yarnpkg.com/jest-jasmine2/-/jest-jasmine2-27.0.6.tgz#fd509a9ed3d92bd6edb68a779f4738b100655b37" + integrity sha512-cjpH2sBy+t6dvCeKBsHpW41mjHzXgsavaFMp+VWRf0eR4EW8xASk1acqmljFtK2DgyIECMv2yCdY41r2l1+4iA== dependencies: "@babel/traverse" "^7.1.0" - "@jest/environment" "^27.0.5" - "@jest/source-map" "^27.0.1" - "@jest/test-result" "^27.0.2" - "@jest/types" "^27.0.2" + "@jest/environment" "^27.0.6" + "@jest/source-map" "^27.0.6" + "@jest/test-result" "^27.0.6" + "@jest/types" "^27.0.6" "@types/node" "*" chalk "^4.0.0" co "^4.6.0" - expect "^27.0.2" + expect "^27.0.6" is-generator-fn "^2.0.0" - jest-each "^27.0.2" - jest-matcher-utils "^27.0.2" - jest-message-util "^27.0.2" - jest-runtime "^27.0.5" - jest-snapshot "^27.0.5" - jest-util "^27.0.2" - pretty-format "^27.0.2" + jest-each "^27.0.6" + jest-matcher-utils "^27.0.6" + jest-message-util "^27.0.6" + jest-runtime "^27.0.6" + jest-snapshot "^27.0.6" + jest-util "^27.0.6" + pretty-format "^27.0.6" throat "^6.0.1" -jest-leak-detector@^27.0.2: - version "27.0.2" - resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-27.0.2.tgz#ce19aa9dbcf7a72a9d58907a970427506f624e69" - integrity sha512-TZA3DmCOfe8YZFIMD1GxFqXUkQnIoOGQyy4hFCA2mlHtnAaf+FeOMxi0fZmfB41ZL+QbFG6BVaZF5IeFIVy53Q== +jest-leak-detector@^27.0.6: + version "27.0.6" + resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-27.0.6.tgz#545854275f85450d4ef4b8fe305ca2a26450450f" + integrity sha512-2/d6n2wlH5zEcdctX4zdbgX8oM61tb67PQt4Xh8JFAIy6LRKUnX528HulkaG6nD5qDl5vRV1NXejCe1XRCH5gQ== dependencies: - jest-get-type "^27.0.1" - pretty-format "^27.0.2" + jest-get-type "^27.0.6" + pretty-format "^27.0.6" -jest-matcher-utils@^27.0.2: - version "27.0.2" - resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-27.0.2.tgz#f14c060605a95a466cdc759acc546c6f4cbfc4f0" - integrity sha512-Qczi5xnTNjkhcIB0Yy75Txt+Ez51xdhOxsukN7awzq2auZQGPHcQrJ623PZj0ECDEMOk2soxWx05EXdXGd1CbA== +jest-matcher-utils@^27.0.6: + version "27.0.6" + resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-27.0.6.tgz#2a8da1e86c620b39459f4352eaa255f0d43e39a9" + integrity sha512-OFgF2VCQx9vdPSYTHWJ9MzFCehs20TsyFi6bIHbk5V1u52zJOnvF0Y/65z3GLZHKRuTgVPY4Z6LVePNahaQ+tA== dependencies: chalk "^4.0.0" - jest-diff "^27.0.2" - jest-get-type "^27.0.1" - pretty-format "^27.0.2" + jest-diff "^27.0.6" + jest-get-type "^27.0.6" + pretty-format "^27.0.6" -jest-message-util@^27.0.2: - version "27.0.2" - resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-27.0.2.tgz#181c9b67dff504d8f4ad15cba10d8b80f272048c" - integrity sha512-rTqWUX42ec2LdMkoUPOzrEd1Tcm+R1KfLOmFK+OVNo4MnLsEaxO5zPDb2BbdSmthdM/IfXxOZU60P/WbWF8BTw== +jest-message-util@^27.0.6: + version "27.0.6" + resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-27.0.6.tgz#158bcdf4785706492d164a39abca6a14da5ab8b5" + integrity sha512-rBxIs2XK7rGy+zGxgi+UJKP6WqQ+KrBbD1YMj517HYN3v2BG66t3Xan3FWqYHKZwjdB700KiAJ+iES9a0M+ixw== dependencies: "@babel/code-frame" "^7.12.13" - "@jest/types" "^27.0.2" + "@jest/types" "^27.0.6" "@types/stack-utils" "^2.0.0" chalk "^4.0.0" graceful-fs "^4.2.4" micromatch "^4.0.4" - pretty-format "^27.0.2" + pretty-format "^27.0.6" slash "^3.0.0" stack-utils "^2.0.3" -jest-mock@^27.0.3: - version "27.0.3" - resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-27.0.3.tgz#5591844f9192b3335c0dca38e8e45ed297d4d23d" - integrity sha512-O5FZn5XDzEp+Xg28mUz4ovVcdwBBPfAhW9+zJLO0Efn2qNbYcDaJvSlRiQ6BCZUCVOJjALicuJQI9mRFjv1o9Q== +jest-mock@^27.0.6: + version "27.0.6" + resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-27.0.6.tgz#0efdd40851398307ba16778728f6d34d583e3467" + integrity sha512-lzBETUoK8cSxts2NYXSBWT+EJNzmUVtVVwS1sU9GwE1DLCfGsngg+ZVSIe0yd0ZSm+y791esiuo+WSwpXJQ5Bw== dependencies: - "@jest/types" "^27.0.2" + "@jest/types" "^27.0.6" "@types/node" "*" jest-pnp-resolver@^1.2.2: @@ -6315,76 +6604,76 @@ resolved "https://registry.yarnpkg.com/jest-pnp-resolver/-/jest-pnp-resolver-1.2.2.tgz#b704ac0ae028a89108a4d040b3f919dfddc8e33c" integrity sha512-olV41bKSMm8BdnuMsewT4jqlZ8+3TCARAXjZGT9jcoSnrfUnRCqnMoF9XEeoWjbzObpqF9dRhHQj0Xb9QdF6/w== -jest-regex-util@^27.0.1: - version "27.0.1" - resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-27.0.1.tgz#69d4b1bf5b690faa3490113c47486ed85dd45b68" - integrity sha512-6nY6QVcpTgEKQy1L41P4pr3aOddneK17kn3HJw6SdwGiKfgCGTvH02hVXL0GU8GEKtPH83eD2DIDgxHXOxVohQ== +jest-regex-util@^27.0.6: + version "27.0.6" + resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-27.0.6.tgz#02e112082935ae949ce5d13b2675db3d8c87d9c5" + integrity sha512-SUhPzBsGa1IKm8hx2F4NfTGGp+r7BXJ4CulsZ1k2kI+mGLG+lxGrs76veN2LF/aUdGosJBzKgXmNCw+BzFqBDQ== -jest-resolve-dependencies@^27.0.5: - version "27.0.5" - resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-27.0.5.tgz#819ccdddd909c65acddb063aac3a49e4ba1ed569" - integrity sha512-xUj2dPoEEd59P+nuih4XwNa4nJ/zRd/g4rMvjHrZPEBWeWRq/aJnnM6mug+B+Nx+ILXGtfWHzQvh7TqNV/WbuA== +jest-resolve-dependencies@^27.0.6: + version "27.0.6" + resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-27.0.6.tgz#3e619e0ef391c3ecfcf6ef4056207a3d2be3269f" + integrity sha512-mg9x9DS3BPAREWKCAoyg3QucCr0n6S8HEEsqRCKSPjPcu9HzRILzhdzY3imsLoZWeosEbJZz6TKasveczzpJZA== dependencies: - "@jest/types" "^27.0.2" - jest-regex-util "^27.0.1" - jest-snapshot "^27.0.5" + "@jest/types" "^27.0.6" + jest-regex-util "^27.0.6" + jest-snapshot "^27.0.6" -jest-resolve@^27.0.5: - version "27.0.5" - resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-27.0.5.tgz#937535a5b481ad58e7121eaea46d1424a1e0c507" - integrity sha512-Md65pngRh8cRuWVdWznXBB5eDt391OJpdBaJMxfjfuXCvOhM3qQBtLMCMTykhuUKiBMmy5BhqCW7AVOKmPrW+Q== +jest-resolve@^27.0.6: + version "27.0.6" + resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-27.0.6.tgz#e90f436dd4f8fbf53f58a91c42344864f8e55bff" + integrity sha512-yKmIgw2LgTh7uAJtzv8UFHGF7Dm7XfvOe/LQ3Txv101fLM8cx2h1QVwtSJ51Q/SCxpIiKfVn6G2jYYMDNHZteA== dependencies: - "@jest/types" "^27.0.2" + "@jest/types" "^27.0.6" chalk "^4.0.0" escalade "^3.1.1" graceful-fs "^4.2.4" jest-pnp-resolver "^1.2.2" - jest-util "^27.0.2" - jest-validate "^27.0.2" + jest-util "^27.0.6" + jest-validate "^27.0.6" resolve "^1.20.0" slash "^3.0.0" -jest-runner@^27.0.5: - version "27.0.5" - resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-27.0.5.tgz#b6fdc587e1a5056339205914294555c554efc08a" - integrity sha512-HNhOtrhfKPArcECgBTcWOc+8OSL8GoFoa7RsHGnfZR1C1dFohxy9eLtpYBS+koybAHlJLZzNCx2Y/Ic3iEtJpQ== +jest-runner@^27.0.6: + version "27.0.6" + resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-27.0.6.tgz#1325f45055539222bbc7256a6976e993ad2f9520" + integrity sha512-W3Bz5qAgaSChuivLn+nKOgjqNxM7O/9JOJoKDCqThPIg2sH/d4A/lzyiaFgnb9V1/w29Le11NpzTJSzga1vyYQ== dependencies: - "@jest/console" "^27.0.2" - "@jest/environment" "^27.0.5" - "@jest/test-result" "^27.0.2" - "@jest/transform" "^27.0.5" - "@jest/types" "^27.0.2" + "@jest/console" "^27.0.6" + "@jest/environment" "^27.0.6" + "@jest/test-result" "^27.0.6" + "@jest/transform" "^27.0.6" + "@jest/types" "^27.0.6" "@types/node" "*" chalk "^4.0.0" emittery "^0.8.1" exit "^0.1.2" graceful-fs "^4.2.4" - jest-docblock "^27.0.1" - jest-environment-jsdom "^27.0.5" - jest-environment-node "^27.0.5" - jest-haste-map "^27.0.5" - jest-leak-detector "^27.0.2" - jest-message-util "^27.0.2" - jest-resolve "^27.0.5" - jest-runtime "^27.0.5" - jest-util "^27.0.2" - jest-worker "^27.0.2" + jest-docblock "^27.0.6" + jest-environment-jsdom "^27.0.6" + jest-environment-node "^27.0.6" + jest-haste-map "^27.0.6" + jest-leak-detector "^27.0.6" + jest-message-util "^27.0.6" + jest-resolve "^27.0.6" + jest-runtime "^27.0.6" + jest-util "^27.0.6" + jest-worker "^27.0.6" source-map-support "^0.5.6" throat "^6.0.1" -jest-runtime@^27.0.5: - version "27.0.5" - resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-27.0.5.tgz#cd5d1aa9754d30ddf9f13038b3cb7b95b46f552d" - integrity sha512-V/w/+VasowPESbmhXn5AsBGPfb35T7jZPGZybYTHxZdP7Gwaa+A0EXE6rx30DshHKA98lVCODbCO8KZpEW3hiQ== +jest-runtime@^27.0.6: + version "27.0.6" + resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-27.0.6.tgz#45877cfcd386afdd4f317def551fc369794c27c9" + integrity sha512-BhvHLRVfKibYyqqEFkybsznKwhrsu7AWx2F3y9G9L95VSIN3/ZZ9vBpm/XCS2bS+BWz3sSeNGLzI3TVQ0uL85Q== dependencies: - "@jest/console" "^27.0.2" - "@jest/environment" "^27.0.5" - "@jest/fake-timers" "^27.0.5" - "@jest/globals" "^27.0.5" - "@jest/source-map" "^27.0.1" - "@jest/test-result" "^27.0.2" - "@jest/transform" "^27.0.5" - "@jest/types" "^27.0.2" + "@jest/console" "^27.0.6" + "@jest/environment" "^27.0.6" + "@jest/fake-timers" "^27.0.6" + "@jest/globals" "^27.0.6" + "@jest/source-map" "^27.0.6" + "@jest/test-result" "^27.0.6" + "@jest/transform" "^27.0.6" + "@jest/types" "^27.0.6" "@types/yargs" "^16.0.0" chalk "^4.0.0" cjs-module-lexer "^1.0.0" @@ -6392,30 +6681,30 @@ exit "^0.1.2" glob "^7.1.3" graceful-fs "^4.2.4" - jest-haste-map "^27.0.5" - jest-message-util "^27.0.2" - jest-mock "^27.0.3" - jest-regex-util "^27.0.1" - jest-resolve "^27.0.5" - jest-snapshot "^27.0.5" - jest-util "^27.0.2" - jest-validate "^27.0.2" + jest-haste-map "^27.0.6" + jest-message-util "^27.0.6" + jest-mock "^27.0.6" + jest-regex-util "^27.0.6" + jest-resolve "^27.0.6" + jest-snapshot "^27.0.6" + jest-util "^27.0.6" + jest-validate "^27.0.6" slash "^3.0.0" strip-bom "^4.0.0" yargs "^16.0.3" -jest-serializer@^27.0.1: - version "27.0.1" - resolved "https://registry.yarnpkg.com/jest-serializer/-/jest-serializer-27.0.1.tgz#2464d04dcc33fb71dc80b7c82e3c5e8a08cb1020" - integrity sha512-svy//5IH6bfQvAbkAEg1s7xhhgHTtXu0li0I2fdKHDsLP2P2MOiscPQIENQep8oU2g2B3jqLyxKKzotZOz4CwQ== +jest-serializer@^27.0.6: + version "27.0.6" + resolved "https://registry.yarnpkg.com/jest-serializer/-/jest-serializer-27.0.6.tgz#93a6c74e0132b81a2d54623251c46c498bb5bec1" + integrity sha512-PtGdVK9EGC7dsaziskfqaAPib6wTViY3G8E5wz9tLVPhHyiDNTZn/xjZ4khAw+09QkoOVpn7vF5nPSN6dtBexA== dependencies: "@types/node" "*" graceful-fs "^4.2.4" -jest-snapshot@^27.0.5: - version "27.0.5" - resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-27.0.5.tgz#6e3b9e8e193685372baff771ba34af631fe4d4d5" - integrity sha512-H1yFYdgnL1vXvDqMrnDStH6yHFdMEuzYQYc71SnC/IJnuuhW6J16w8GWG1P+qGd3Ag3sQHjbRr0TcwEo/vGS+g== +jest-snapshot@^27.0.6: + version "27.0.6" + resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-27.0.6.tgz#f4e6b208bd2e92e888344d78f0f650bcff05a4bf" + integrity sha512-NTHaz8He+ATUagUgE7C/UtFcRoHqR2Gc+KDfhQIyx+VFgwbeEMjeP+ILpUTLosZn/ZtbNdCF5LkVnN/l+V751A== dependencies: "@babel/core" "^7.7.2" "@babel/generator" "^7.7.2" @@ -6423,79 +6712,79 @@ "@babel/plugin-syntax-typescript" "^7.7.2" "@babel/traverse" "^7.7.2" "@babel/types" "^7.0.0" - "@jest/transform" "^27.0.5" - "@jest/types" "^27.0.2" + "@jest/transform" "^27.0.6" + "@jest/types" "^27.0.6" "@types/babel__traverse" "^7.0.4" "@types/prettier" "^2.1.5" babel-preset-current-node-syntax "^1.0.0" chalk "^4.0.0" - expect "^27.0.2" + expect "^27.0.6" graceful-fs "^4.2.4" - jest-diff "^27.0.2" - jest-get-type "^27.0.1" - jest-haste-map "^27.0.5" - jest-matcher-utils "^27.0.2" - jest-message-util "^27.0.2" - jest-resolve "^27.0.5" - jest-util "^27.0.2" + jest-diff "^27.0.6" + jest-get-type "^27.0.6" + jest-haste-map "^27.0.6" + jest-matcher-utils "^27.0.6" + jest-message-util "^27.0.6" + jest-resolve "^27.0.6" + jest-util "^27.0.6" natural-compare "^1.4.0" - pretty-format "^27.0.2" + pretty-format "^27.0.6" semver "^7.3.2" -jest-util@^27.0.2: - version "27.0.2" - resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-27.0.2.tgz#fc2c7ace3c75ae561cf1e5fdb643bf685a5be7c7" - integrity sha512-1d9uH3a00OFGGWSibpNYr+jojZ6AckOMCXV2Z4K3YXDnzpkAaXQyIpY14FOJPiUmil7CD+A6Qs+lnnh6ctRbIA== +jest-util@^27.0.6: + version "27.0.6" + resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-27.0.6.tgz#e8e04eec159de2f4d5f57f795df9cdc091e50297" + integrity sha512-1JjlaIh+C65H/F7D11GNkGDDZtDfMEM8EBXsvd+l/cxtgQ6QhxuloOaiayt89DxUvDarbVhqI98HhgrM1yliFQ== dependencies: - "@jest/types" "^27.0.2" + "@jest/types" "^27.0.6" "@types/node" "*" chalk "^4.0.0" graceful-fs "^4.2.4" is-ci "^3.0.0" picomatch "^2.2.3" -jest-validate@^27.0.2: - version "27.0.2" - resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-27.0.2.tgz#7fe2c100089449cd5cbb47a5b0b6cb7cda5beee5" - integrity sha512-UgBF6/oVu1ofd1XbaSotXKihi8nZhg0Prm8twQ9uCuAfo59vlxCXMPI/RKmrZEVgi3Nd9dS0I8A0wzWU48pOvg== +jest-validate@^27.0.6: + version "27.0.6" + resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-27.0.6.tgz#930a527c7a951927df269f43b2dc23262457e2a6" + integrity sha512-yhZZOaMH3Zg6DC83n60pLmdU1DQE46DW+KLozPiPbSbPhlXXaiUTDlhHQhHFpaqIFRrInko1FHXjTRpjWRuWfA== dependencies: - "@jest/types" "^27.0.2" + "@jest/types" "^27.0.6" camelcase "^6.2.0" chalk "^4.0.0" - jest-get-type "^27.0.1" + jest-get-type "^27.0.6" leven "^3.1.0" - pretty-format "^27.0.2" + pretty-format "^27.0.6" -jest-watcher@^27.0.2: - version "27.0.2" - resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-27.0.2.tgz#dab5f9443e2d7f52597186480731a8c6335c5deb" - integrity sha512-8nuf0PGuTxWj/Ytfw5fyvNn/R80iXY8QhIT0ofyImUvdnoaBdT6kob0GmhXR+wO+ALYVnh8bQxN4Tjfez0JgkA== +jest-watcher@^27.0.6: + version "27.0.6" + resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-27.0.6.tgz#89526f7f9edf1eac4e4be989bcb6dec6b8878d9c" + integrity sha512-/jIoKBhAP00/iMGnTwUBLgvxkn7vsOweDrOTSPzc7X9uOyUtJIDthQBTI1EXz90bdkrxorUZVhJwiB69gcHtYQ== dependencies: - "@jest/test-result" "^27.0.2" - "@jest/types" "^27.0.2" + "@jest/test-result" "^27.0.6" + "@jest/types" "^27.0.6" "@types/node" "*" ansi-escapes "^4.2.1" chalk "^4.0.0" - jest-util "^27.0.2" + jest-util "^27.0.6" string-length "^4.0.1" -jest-worker@^27.0.2: - version "27.0.2" - resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-27.0.2.tgz#4ebeb56cef48b3e7514552f80d0d80c0129f0b05" - integrity sha512-EoBdilOTTyOgmHXtw/cPc+ZrCA0KJMrkXzkrPGNwLmnvvlN1nj7MPrxpT7m+otSv2e1TLaVffzDnE/LB14zJMg== +jest-worker@^27.0.6: + version "27.0.6" + resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-27.0.6.tgz#a5fdb1e14ad34eb228cfe162d9f729cdbfa28aed" + integrity sha512-qupxcj/dRuA3xHPMUd40gr2EaAurFbkwzOh7wfPaeE9id7hyjURRQoqNfHifHK3XjJU6YJJUQKILGUnwGPEOCA== dependencies: "@types/node" "*" merge-stream "^2.0.0" supports-color "^8.0.0" -jest@^27.0.5: - version "27.0.5" - resolved "https://registry.yarnpkg.com/jest/-/jest-27.0.5.tgz#141825e105514a834cc8d6e44670509e8d74c5f2" - integrity sha512-4NlVMS29gE+JOZvgmSAsz3eOjkSsHqjTajlIsah/4MVSmKvf3zFP/TvgcLoWe2UVHiE9KF741sReqhF0p4mqbQ== +jest@^27.0.6: + version "27.0.6" + resolved "https://registry.yarnpkg.com/jest/-/jest-27.0.6.tgz#10517b2a628f0409087fbf473db44777d7a04505" + integrity sha512-EjV8aETrsD0wHl7CKMibKwQNQc3gIRBXlTikBmmHUeVMKaPFxdcUIBfoDqTSXDoGJIivAYGqCWVlzCSaVjPQsA== dependencies: - "@jest/core" "^27.0.5" + "@jest/core" "^27.0.6" import-local "^3.0.2" - jest-cli "^27.0.5" + jest-cli "^27.0.6" js-sha3@0.5.7, js-sha3@^0.5.7: version "0.5.7" @@ -6931,6 +7220,13 @@ typescript "^3.9.5" walkdir "^0.4.1" +magic-string@^0.25.5, magic-string@^0.25.7: + version "0.25.7" + resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.25.7.tgz#3f497d6fd34c669c6798dcb821f2ef31f5445051" + integrity sha512-4CrMT5DOHTDk4HYDlzmwu4FVCcIYI8gauveasrdCu2IKIFOJ3f0v/8MDGJCDL9oD2ppz/Av1b0Nj345H9M+XIA== + dependencies: + sourcemap-codec "^1.4.4" + make-dir@^2.0.0, make-dir@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-2.1.0.tgz#5f0310e18b8be898cc07009295a30ae41e91e6f5" @@ -7366,6 +7662,11 @@ resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.73.tgz#dd4e81ddd5277ff846b80b52bb40c49edf7a7b20" integrity sha512-uW7fodD6pyW2FZNZnp/Z3hvWKeEW1Y8R1+1CnErE8cXFXzl5blBOoVB41CvMer6P6Q0S5FXDwcHgFd1Wj0U9zg== +node-releases@^1.1.73: + version "1.1.74" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.74.tgz#e5866488080ebaa70a93b91144ccde06f3c3463e" + integrity sha512-caJBVempXZPepZoZAPCWRTNxYQ+xtG/KAi4ozTA5A+nJ7IU+kLQCbqaUjb5Rwy14M9upBWiQ4NutcmW04LJSRw== + node-source-walk@^4.0.0, node-source-walk@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/node-source-walk/-/node-source-walk-4.2.0.tgz#c2efe731ea8ba9c03c562aa0a9d984e54f27bc2c" @@ -7812,7 +8113,7 @@ resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns= -picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.3: +picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.2, picomatch@^2.2.3: version "2.3.0" resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.0.tgz#f1f061de8f6a4bf022892e2d128234fb98302972" integrity sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw== @@ -7994,17 +8295,17 @@ resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.19.1.tgz#f7d7f5ff8a9cd872a7be4ca142095956a60797cb" integrity sha512-s7PoyDv/II1ObgQunCbB9PdLmUcBZcnWOcxDh7O0N/UwDEsHyqkW+Qh28jW+mVuCdx7gLB0BotYI1Y6uI9iyew== -prettier@^2.3.1: - version "2.3.1" - resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.3.1.tgz#76903c3f8c4449bc9ac597acefa24dc5ad4cbea6" - integrity sha512-p+vNbgpLjif/+D+DwAZAbndtRrR0md0MwfmOVN9N+2RgyACMT+7tfaRnT+WDPkqnuVwleyuBIG2XBxKDme3hPA== +prettier@^2.3.2: + version "2.3.2" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.3.2.tgz#ef280a05ec253712e486233db5c6f23441e7342d" + integrity sha512-lnJzDfJ66zkMy58OL5/NY5zp70S7Nz6KqcKkXYzn2tMVrNxvbqaBpg7H3qHaLxCJ5lNMsGuM8+ohS7cZrthdLQ== -pretty-format@^27.0.2: - version "27.0.2" - resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-27.0.2.tgz#9283ff8c4f581b186b2d4da461617143dca478a4" - integrity sha512-mXKbbBPnYTG7Yra9qFBtqj+IXcsvxsvOBco3QHxtxTl+hHKq6QdzMZ+q0CtL4ORHZgwGImRr2XZUX2EWzORxig== +pretty-format@^27.0.6: + version "27.0.6" + resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-27.0.6.tgz#ab770c47b2c6f893a21aefc57b75da63ef49a11f" + integrity sha512-8tGD7gBIENgzqA+UBzObyWqQ5B778VIFZA/S66cclyd5YkFLYs2Js7gxDKf0MXtTc9zcS7t1xhdfcElJ3YIvkQ== dependencies: - "@jest/types" "^27.0.2" + "@jest/types" "^27.0.6" ansi-regex "^5.0.0" ansi-styles "^5.0.0" react-is "^17.0.1" @@ -8454,7 +8755,7 @@ resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo= -resolve@^1.1.6, resolve@^1.10.0, resolve@^1.10.1, resolve@^1.13.1, resolve@^1.14.2, resolve@^1.19.0, resolve@^1.20.0, resolve@^1.3.2: +resolve@^1.1.6, resolve@^1.10.0, resolve@^1.10.1, resolve@^1.13.1, resolve@^1.14.2, resolve@^1.17.0, resolve@^1.19.0, resolve@^1.20.0, resolve@^1.3.2: version "1.20.0" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.20.0.tgz#629a013fb3f70755d6f0b7935cc1c2c5378b1975" integrity sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A== @@ -8524,6 +8825,13 @@ dependencies: bn.js "^4.11.1" +rollup@^2.56.2: + version "2.56.2" + resolved "https://registry.yarnpkg.com/rollup/-/rollup-2.56.2.tgz#a045ff3f6af53ee009b5f5016ca3da0329e5470f" + integrity sha512-s8H00ZsRi29M2/lGdm1u8DJpJ9ML8SUOpVVBd33XNeEeL3NVaTiUcSBHzBdF3eAyR0l7VSpsuoVUGrRHq7aPwQ== + optionalDependencies: + fsevents "~2.3.2" + run-async@^2.4.0: version "2.4.1" resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.4.1.tgz#8440eccf99ea3e70bd409d49aab88e10c189a455" @@ -8543,10 +8851,10 @@ dependencies: tslib "^1.9.0" -rxjs@^7.2.0: - version "7.2.0" - resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.2.0.tgz#5cd12409639e9514a71c9f5f9192b2c4ae94de31" - integrity sha512-aX8w9OpKrQmiPKfT1bqETtUr9JygIz6GZ+gql8v7CijClsP0laoFUdKzxFAoWuRdSlOdU2+crss+cMf+cqMTnw== +rxjs@^7.3.0: + version "7.3.0" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.3.0.tgz#39fe4f3461dc1e50be1475b2b85a0a88c1e938c6" + integrity sha512-p2yuGIg9S1epc3vrjKf6iVb3RCaAYjYskkO+jHIaV0IjOPlJop4UnodOoFb2xeNwlguqLYvGw1b1McillYb5Gw== dependencies: tslib "~2.1.0" @@ -8894,6 +9202,11 @@ resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.3.tgz#5302f8169031735226544092e64981f751750383" integrity sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ== +sourcemap-codec@^1.4.4: + version "1.4.8" + resolved "https://registry.yarnpkg.com/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz#ea804bd94857402e6992d05a38ef1ae35a9ab4c4" + integrity sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA== + spdx-correct@^3.0.0: version "3.1.1" resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.1.1.tgz#dece81ac9c1e6713e5f7d1b6f17d468fa53d89a9" @@ -9453,16 +9766,16 @@ dependencies: safe-buffer "^5.0.1" +tweetnacl@1.x.x, tweetnacl@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-1.0.3.tgz#ac0af71680458d8a6378d0d0d050ab1407d35596" + integrity sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw== + tweetnacl@^0.14.3, tweetnacl@~0.14.0: version "0.14.5" resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q= -tweetnacl@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-1.0.3.tgz#ac0af71680458d8a6378d0d0d050ab1407d35596" - integrity sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw== - type-check@^0.4.0, type-check@~0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1" @@ -9527,11 +9840,16 @@ resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.9.10.tgz#70f3910ac7a51ed6bef79da7800690b19bf778b8" integrity sha512-w6fIxVE/H1PkLKcCPsFqKE7Kv7QUwhU8qQY2MueZXWx5cPZdwFupLgKK3vntcK98BtNHZtAF4LA/yl2a7k8R6Q== -typescript@^4.2.4, typescript@^4.3.4: +typescript@^4.2.4: version "4.3.4" resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.3.4.tgz#3f85b986945bcf31071decdd96cf8bfa65f9dcbc" integrity sha512-uauPG7XZn9F/mo+7MrsRjyvbxFpzemRjKEZXS4AK83oP2KKOJPvb+9cO/gmnv8arWZvhnjVOXz7B49m1l0e9Ew== +typescript@^4.3.5: + version "4.3.5" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.3.5.tgz#4d1c37cc16e893973c45a06886b7113234f119f4" + integrity sha512-DqQgihaQ9cUrskJo9kIyW/+g0Vxsk8cDtZ52a3NGh0YNTfpUSArXSohyUGnvbPazEPLu398C0UxmKSOrPumUzA== + uglify-js@^3.1.4: version "3.13.9" resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.13.9.tgz#4d8d21dcd497f29cfd8e9378b9df123ad025999b" @@ -10339,7 +10657,7 @@ y18n "^5.0.5" yargs-parser "^20.2.2" -yargs@^17.0.0, yargs@^17.0.1: +yargs@^17.0.0: version "17.0.1" resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.0.1.tgz#6a1ced4ed5ee0b388010ba9fd67af83b9362e0bb" integrity sha512-xBBulfCc8Y6gLFcrPvtqKz9hz8SO0l1Ni8GgDekvBX2ro0HRQImDGnikfc33cgzcYUSncapnNcZDjVFIH3f6KQ== @@ -10352,6 +10670,19 @@ y18n "^5.0.5" yargs-parser "^20.2.2" +yargs@^17.1.0, yargs@^17.1.1: + version "17.1.1" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.1.1.tgz#c2a8091564bdb196f7c0a67c1d12e5b85b8067ba" + integrity sha512-c2k48R0PwKIqKhPMWjeiF6y2xY/gPMUlro0sgxqXpbOIohWiLNXWslsootttv7E1e73QPAMQSg5FeySbVcpsPQ== + dependencies: + cliui "^7.0.2" + escalade "^3.1.1" + get-caller-file "^2.0.5" + require-directory "^2.1.1" + string-width "^4.2.0" + y18n "^5.0.5" + yargs-parser "^20.2.2" + yn@3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50"