From 36e327173faf2aa955f2c4e1af432ca03a0fef47 Mon Sep 17 00:00:00 2001 From: ashi20192020 <> Date: Wed, 28 Apr 2021 22:18:23 +0530 Subject: [PATCH 01/12] Imported asset pallet --- Cargo.lock | 1 + bin/node/runtime/src/lib.rs | 1 + frame/social-nft/Cargo.toml | 4 +++- frame/social-nft/src/lib.rs | 6 +++--- 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4b0fdfac2..0c99ecada 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5297,6 +5297,7 @@ dependencies = [ "chainbridge", "frame-support", "frame-system", + "pallet-assets", "pallet-balances", "parity-scale-codec", "serde", diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs index 4a6aa8b82..d10b6d066 100644 --- a/bin/node/runtime/src/lib.rs +++ b/bin/node/runtime/src/lib.rs @@ -1134,6 +1134,7 @@ impl pallet_social_bridge::Config for Runtime { impl pallet_social_nft::Config for Runtime { type Event = Event; + type FungibleToken = Assets; type Identifier = Erc721Id; } diff --git a/frame/social-nft/Cargo.toml b/frame/social-nft/Cargo.toml index ddb551423..0d0125707 100644 --- a/frame/social-nft/Cargo.toml +++ b/frame/social-nft/Cargo.toml @@ -16,6 +16,7 @@ sp-std = { version = '3.0.0', default-features = false, path = '../../primitives sp-runtime = { version = '3.0.0', default-features = false, path = '../../primitives/runtime' } sp-io = { version = '3.0.0', default-features = false, path = '../../primitives/io' } sp-core = { version = '3.0.0', default-features = false, path = '../../primitives/core' } +pallet-assets = { default-features = false, version = '3.0.0', path = '../assets' } [dev-dependencies] pallet-balances = { version = '3.0.0',default-features = false, path = '../balances' } @@ -33,5 +34,6 @@ std = [ 'sp-core/std', 'frame-support/std', 'frame-system/std', - 'chainbridge/std' + 'chainbridge/std', + 'pallet-assets/std', ] diff --git a/frame/social-nft/src/lib.rs b/frame/social-nft/src/lib.rs index b017e5e86..e54361ca4 100644 --- a/frame/social-nft/src/lib.rs +++ b/frame/social-nft/src/lib.rs @@ -10,7 +10,7 @@ use frame_system::{self as system, ensure_root, ensure_signed}; use sp_core::U256; use sp_runtime::RuntimeDebug; use sp_std::prelude::*; - +use pallet_assets::{Fungible, IssueAndBurn}; mod mock; mod tests; @@ -22,9 +22,9 @@ pub struct Erc721Token { pub metadata: Vec, } -pub trait Config: system::Config { +pub trait Config: system::Config + pallet_assets::Config { type Event: From> + Into<::Event>; - + type FungibleToken: IssueAndBurn; /// Some identifier for this token type, possibly the originating ethereum address. /// This is not explicitly used for anything, but may reflect the bridge's notion of resource ID. type Identifier: Get<[u8; 32]>; From 93fb6132b908893c84b38d3a902ecabc77d37c31 Mon Sep 17 00:00:00 2001 From: Ayush Date: Thu, 29 Apr 2021 06:58:10 +0530 Subject: [PATCH 02/12] Added setAsk method --- frame/social-nft/src/lib.rs | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/frame/social-nft/src/lib.rs b/frame/social-nft/src/lib.rs index e54361ca4..f10faf730 100644 --- a/frame/social-nft/src/lib.rs +++ b/frame/social-nft/src/lib.rs @@ -41,6 +41,8 @@ decl_event! { Transferred(AccountId, AccountId, NftId), /// Token removed from the system Burned(NftId), + /// Set Ask Amount + SetAskAmount(NftId), } } @@ -65,6 +67,8 @@ decl_storage! { pub TokenCount get(fn token_count): U256 = U256::zero(); /// Maximum token id pub MaxTokenId get(fn max_token_id): U256 = U256::zero(); + /// Set ask amount for token id + pub TokenAmount get(fn amount_of): map hasher(opaque_blake2_256) NftId => T::Balance; } } @@ -102,6 +106,17 @@ decl_module! { Self::burn_token(owner, id)?; + Ok(()) + } + + #[weight = 195_000_000] + pub fn set_ask(origin, id: NftId, amount: T::Balance) -> DispatchResult { + let sender = ensure_signed(origin)?; + + let owner = Self::owner_of(id).ok_or(Error::::NftIdDoesNotExist)?; + ensure!(owner == sender, Error::::NotOwner); + Self::set_ask_token(owner, id, amount)?; + Ok(()) } } @@ -154,4 +169,11 @@ impl Module { Ok(()) } + + pub fn set_ask_token(_owner: T::AccountId, id: NftId, amount: T::Balance) -> DispatchResult { + + >::insert(&id, amount); + Self::deposit_event(RawEvent::SetAskAmount(id)); + Ok(()) + } } From dc9a677d624a65cbde2c3cb024926f6bc07cea18 Mon Sep 17 00:00:00 2001 From: Ayush <> Date: Fri, 30 Apr 2021 09:15:36 +0530 Subject: [PATCH 03/12] Imported timestamp pallet and added setbid method --- Cargo.lock | 1 + bin/node/runtime/src/lib.rs | 1 - frame/social-nft/Cargo.toml | 2 ++ frame/social-nft/src/lib.rs | 58 +++++++++++++++++++++++++++++++------ 4 files changed, 52 insertions(+), 10 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0c99ecada..05fe238a7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5299,6 +5299,7 @@ dependencies = [ "frame-system", "pallet-assets", "pallet-balances", + "pallet-timestamp", "parity-scale-codec", "serde", "sp-core", diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs index d10b6d066..4a6aa8b82 100644 --- a/bin/node/runtime/src/lib.rs +++ b/bin/node/runtime/src/lib.rs @@ -1134,7 +1134,6 @@ impl pallet_social_bridge::Config for Runtime { impl pallet_social_nft::Config for Runtime { type Event = Event; - type FungibleToken = Assets; type Identifier = Erc721Id; } diff --git a/frame/social-nft/Cargo.toml b/frame/social-nft/Cargo.toml index 0d0125707..ef731cba1 100644 --- a/frame/social-nft/Cargo.toml +++ b/frame/social-nft/Cargo.toml @@ -17,6 +17,7 @@ sp-runtime = { version = '3.0.0', default-features = false, path = '../../primit sp-io = { version = '3.0.0', default-features = false, path = '../../primitives/io' } sp-core = { version = '3.0.0', default-features = false, path = '../../primitives/core' } pallet-assets = { default-features = false, version = '3.0.0', path = '../assets' } +pallet-timestamp = { version = '3.0.0',default-features = false, path = '../timestamp' } [dev-dependencies] pallet-balances = { version = '3.0.0',default-features = false, path = '../balances' } @@ -36,4 +37,5 @@ std = [ 'frame-system/std', 'chainbridge/std', 'pallet-assets/std', + 'pallet-timestamp/std', ] diff --git a/frame/social-nft/src/lib.rs b/frame/social-nft/src/lib.rs index f10faf730..18c3dca88 100644 --- a/frame/social-nft/src/lib.rs +++ b/frame/social-nft/src/lib.rs @@ -10,7 +10,8 @@ use frame_system::{self as system, ensure_root, ensure_signed}; use sp_core::U256; use sp_runtime::RuntimeDebug; use sp_std::prelude::*; -use pallet_assets::{Fungible, IssueAndBurn}; +use sp_runtime::traits::Zero; + mod mock; mod tests; @@ -22,9 +23,8 @@ pub struct Erc721Token { pub metadata: Vec, } -pub trait Config: system::Config + pallet_assets::Config { +pub trait Config: system::Config + pallet_assets::Config + pallet_timestamp::Config { type Event: From> + Into<::Event>; - type FungibleToken: IssueAndBurn; /// Some identifier for this token type, possibly the originating ethereum address. /// This is not explicitly used for anything, but may reflect the bridge's notion of resource ID. type Identifier: Get<[u8; 32]>; @@ -43,6 +43,8 @@ decl_event! { Burned(NftId), /// Set Ask Amount SetAskAmount(NftId), + /// Set Ask Amount + SetBidAmount(NftId), } } @@ -54,6 +56,8 @@ decl_error! { TokenAlreadyExists, /// Origin is not owner NotOwner, + /// Not For Sale + NotForSale, } } @@ -68,7 +72,11 @@ decl_storage! { /// Maximum token id pub MaxTokenId get(fn max_token_id): U256 = U256::zero(); /// Set ask amount for token id - pub TokenAmount get(fn amount_of): map hasher(opaque_blake2_256) NftId => T::Balance; + pub TokenAskAmount get(fn ask_token): double_map hasher(opaque_blake2_256) NftId, + hasher(twox_64_concat) T::AssetId => (T::Balance, T::AccountId); + /// Maps tokenId to owner + pub TokenBidAmount get(fn bid_token): map hasher(opaque_blake2_256) T::AccountId => + (T::Balance, T::AssetId, T::Moment); } } @@ -110,12 +118,23 @@ decl_module! { } #[weight = 195_000_000] - pub fn set_ask(origin, id: NftId, amount: T::Balance) -> DispatchResult { + pub fn set_ask(origin, nft_id: NftId, token_id: T::AssetId, amount: T::Balance) -> DispatchResult { let sender = ensure_signed(origin)?; - let owner = Self::owner_of(id).ok_or(Error::::NftIdDoesNotExist)?; + let owner = Self::owner_of(nft_id).ok_or(Error::::NftIdDoesNotExist)?; ensure!(owner == sender, Error::::NotOwner); - Self::set_ask_token(owner, id, amount)?; + Self::set_ask_token(owner, nft_id, token_id, amount, sender)?; + + Ok(()) + } + + #[weight = 195_000_000] + pub fn set_bid(origin, nft_id: NftId, token_id: T::AssetId, amount: T::Balance, dead_line: T::Moment) -> DispatchResult { + let sender = ensure_signed(origin)?; + + let owner = Self::owner_of(nft_id).ok_or(Error::::NftIdDoesNotExist)?; + + Self::set_bid_token(owner, nft_id, token_id, amount, dead_line, sender)?; Ok(()) } @@ -170,10 +189,31 @@ impl Module { Ok(()) } - pub fn set_ask_token(_owner: T::AccountId, id: NftId, amount: T::Balance) -> DispatchResult { + pub fn set_ask_token(_owner: T::AccountId, id: NftId, token_id: T::AssetId, amount: T::Balance, sender: T::AccountId) -> DispatchResult { - >::insert(&id, amount); + >::insert(&id, token_id, (amount, sender)); Self::deposit_event(RawEvent::SetAskAmount(id)); Ok(()) } + + pub fn set_bid_token(_owner: T::AccountId, id: NftId, token_id: T::AssetId, amount: T::Balance, dead_line: T::Moment, sender: T::AccountId) -> DispatchResult { + + let (ask_token, _) = TokenAskAmount::::get(id, token_id); + + ensure!(ask_token.is_zero(), Error::::NotForSale); + let now_timestamp = >::now(); + + if amount > ask_token && dead_line >=now_timestamp { + Self::execute_trade(); + } else { + >::insert(&sender, (amount, token_id, dead_line)); + Self::deposit_event(RawEvent::SetBidAmount(id)); + } + + Ok(()) + } + + fn execute_trade() -> DispatchResult { + Ok(()) + } } From 0f0882065a2e50b893ecafad1715873a6741b832 Mon Sep 17 00:00:00 2001 From: Ayush <> Date: Fri, 30 Apr 2021 10:27:54 +0530 Subject: [PATCH 04/12] Added creator in nft pallet --- frame/social-nft/src/lib.rs | 33 +++++++++++++++++++-------------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/frame/social-nft/src/lib.rs b/frame/social-nft/src/lib.rs index 18c3dca88..42c72ee39 100644 --- a/frame/social-nft/src/lib.rs +++ b/frame/social-nft/src/lib.rs @@ -66,7 +66,7 @@ decl_storage! { /// Maps tokenId to Erc721 object pub Tokens get(fn tokens): map hasher(opaque_blake2_256) NftId => Option; /// Maps tokenId to owner - pub TokenOwner get(fn owner_of): map hasher(opaque_blake2_256) NftId => Option; + pub TokenCreatorOwner get(fn owner_of): map hasher(opaque_blake2_256) NftId => (T::AccountId, T::AccountId); /// Total number of tokens in existence pub TokenCount get(fn token_count): U256 = U256::zero(); /// Maximum token id @@ -110,7 +110,8 @@ decl_module! { pub fn burn(origin, id: NftId) -> DispatchResult { let _sender = ensure_signed(origin)?; - let owner = Self::owner_of(id).ok_or(Error::::NftIdDoesNotExist)?; + ensure!(TokenCreatorOwner::::contains_key(id), Error::::NftIdDoesNotExist); + let (_, owner) = Self::owner_of(id); Self::burn_token(owner, id)?; @@ -121,9 +122,10 @@ decl_module! { pub fn set_ask(origin, nft_id: NftId, token_id: T::AssetId, amount: T::Balance) -> DispatchResult { let sender = ensure_signed(origin)?; - let owner = Self::owner_of(nft_id).ok_or(Error::::NftIdDoesNotExist)?; + ensure!(TokenCreatorOwner::::contains_key(nft_id), Error::::NftIdDoesNotExist); + let (_, owner) = Self::owner_of(nft_id); ensure!(owner == sender, Error::::NotOwner); - Self::set_ask_token(owner, nft_id, token_id, amount, sender)?; + Self::set_ask_token(owner, nft_id, token_id, amount)?; Ok(()) } @@ -132,9 +134,10 @@ decl_module! { pub fn set_bid(origin, nft_id: NftId, token_id: T::AssetId, amount: T::Balance, dead_line: T::Moment) -> DispatchResult { let sender = ensure_signed(origin)?; - let owner = Self::owner_of(nft_id).ok_or(Error::::NftIdDoesNotExist)?; + ensure!(TokenCreatorOwner::::contains_key(nft_id), Error::::NftIdDoesNotExist); + let (_, owner) = Self::owner_of(nft_id); - Self::set_bid_token(owner, nft_id, token_id, amount, dead_line, sender)?; + Self::set_bid_token(sender, nft_id, token_id, amount, dead_line)?; Ok(()) } @@ -149,7 +152,7 @@ impl Module { let new_token = Erc721Token { id, metadata }; ::insert(&id, new_token); - >::insert(&id, owner.clone()); + >::insert(&id, (owner.clone(), owner.clone())); let new_total = ::get().saturating_add(U256::one()); ::put(new_total); if ::get() < id { @@ -164,10 +167,11 @@ impl Module { /// Modifies ownership of a token pub fn transfer_from(from: T::AccountId, to: T::AccountId, id: NftId) -> DispatchResult { // Check from is owner and token exists - let owner = Self::owner_of(id).ok_or(Error::::NftIdDoesNotExist)?; + ensure!(TokenCreatorOwner::::contains_key(id), Error::::NftIdDoesNotExist); + let (_, owner) = Self::owner_of(id); ensure!(owner == from, Error::::NotOwner); // Update owner - >::insert(&id, to.clone()); + TokenCreatorOwner::::mutate(id, |(creator, owner)| *owner = to.clone()); Self::deposit_event(RawEvent::Transferred(from, to, id)); @@ -176,11 +180,12 @@ impl Module { /// Deletes a token from the system. pub fn burn_token(from: T::AccountId, id: NftId) -> DispatchResult { - let owner = Self::owner_of(id).ok_or(Error::::NftIdDoesNotExist)?; + ensure!(TokenCreatorOwner::::contains_key(id), Error::::NftIdDoesNotExist); + let (_, owner) = Self::owner_of(id); ensure!(owner == from, Error::::NotOwner); ::remove(&id); - >::remove(&id); + >::remove(&id); let new_total = ::get().saturating_sub(U256::one()); ::put(new_total); @@ -189,14 +194,14 @@ impl Module { Ok(()) } - pub fn set_ask_token(_owner: T::AccountId, id: NftId, token_id: T::AssetId, amount: T::Balance, sender: T::AccountId) -> DispatchResult { + pub fn set_ask_token(owner: T::AccountId, id: NftId, token_id: T::AssetId, amount: T::Balance) -> DispatchResult { - >::insert(&id, token_id, (amount, sender)); + >::insert(&id, token_id, (amount, owner)); Self::deposit_event(RawEvent::SetAskAmount(id)); Ok(()) } - pub fn set_bid_token(_owner: T::AccountId, id: NftId, token_id: T::AssetId, amount: T::Balance, dead_line: T::Moment, sender: T::AccountId) -> DispatchResult { + pub fn set_bid_token(sender: T::AccountId, id: NftId, token_id: T::AssetId, amount: T::Balance, dead_line: T::Moment) -> DispatchResult { let (ask_token, _) = TokenAskAmount::::get(id, token_id); From e8c0aaede6e37684020ce4ef4a954f4b8d94f03d Mon Sep 17 00:00:00 2001 From: Ayush <> Date: Fri, 30 Apr 2021 12:31:44 +0530 Subject: [PATCH 05/12] Introduced Royalty, refactored mint method, added functionality to execute trade --- bin/node/runtime/src/lib.rs | 2 +- frame/social-bridge/src/lib.rs | 4 ++-- frame/social-nft/src/lib.rs | 41 +++++++++++++++++++++------------- 3 files changed, 28 insertions(+), 19 deletions(-) diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs index 4a6aa8b82..cb88fe449 100644 --- a/bin/node/runtime/src/lib.rs +++ b/bin/node/runtime/src/lib.rs @@ -59,7 +59,7 @@ use sp_runtime::curve::PiecewiseLinear; use sp_runtime::transaction_validity::{TransactionValidity, TransactionSource, TransactionPriority}; use sp_runtime::traits::{ self, BlakeTwo256, Block as BlockT, StaticLookup, SaturatedConversion, - ConvertInto, OpaqueKeys, NumberFor, Saturating, + ConvertInto, OpaqueKeys, NumberFor, }; use sp_version::RuntimeVersion; #[cfg(any(feature = "std", test))] diff --git a/frame/social-bridge/src/lib.rs b/frame/social-bridge/src/lib.rs index e8446cc82..ef2df1672 100644 --- a/frame/social-bridge/src/lib.rs +++ b/frame/social-bridge/src/lib.rs @@ -139,9 +139,9 @@ decl_module! { /// Allows the bridge to issue new erc721 tokens #[weight = 195_000_000] - pub fn mint_erc721(origin, recipient: T::AccountId, id: U256, metadata: Vec, r_id: ResourceId) -> DispatchResult { + pub fn mint_erc721(origin, recipient: T::AccountId, id: U256, metadata: Vec, royalty: T::Balance) -> DispatchResult { T::BridgeOrigin::ensure_origin(origin)?; - >::mint_token(recipient, id, metadata)?; + >::mint_token(recipient, id, metadata, royalty)?; Ok(()) } } diff --git a/frame/social-nft/src/lib.rs b/frame/social-nft/src/lib.rs index 42c72ee39..92222c2f3 100644 --- a/frame/social-nft/src/lib.rs +++ b/frame/social-nft/src/lib.rs @@ -6,21 +6,24 @@ use frame_support::{ decl_error, decl_event, decl_module, decl_storage, dispatch::DispatchResult, ensure, traits::Get, }; -use frame_system::{self as system, ensure_root, ensure_signed}; +use frame_system::{self as system, ensure_signed}; use sp_core::U256; use sp_runtime::RuntimeDebug; use sp_std::prelude::*; -use sp_runtime::traits::Zero; - +use sp_runtime::traits::{Zero, One}; +use sp_runtime::{ + traits::Saturating, +}; mod mock; mod tests; type NftId = U256; #[derive(PartialEq, Eq, Clone, Encode, Decode, RuntimeDebug)] -pub struct Erc721Token { +pub struct Erc721Token { pub id: NftId, pub metadata: Vec, + pub royalty: T::Balance, } pub trait Config: system::Config + pallet_assets::Config + pallet_timestamp::Config { @@ -64,7 +67,7 @@ decl_error! { decl_storage! { trait Store for Module as SocialNFT { /// Maps tokenId to Erc721 object - pub Tokens get(fn tokens): map hasher(opaque_blake2_256) NftId => Option; + pub Tokens get(fn tokens): map hasher(opaque_blake2_256) NftId => Option>; /// Maps tokenId to owner pub TokenCreatorOwner get(fn owner_of): map hasher(opaque_blake2_256) NftId => (T::AccountId, T::AccountId); /// Total number of tokens in existence @@ -87,10 +90,10 @@ decl_module! { /// Creates a new token with the given token ID and metadata, and gives ownership to owner #[weight = 195_000_000] - pub fn mint(origin, owner: T::AccountId, id: NftId, metadata: Vec) -> DispatchResult { + pub fn mint(origin, owner: T::AccountId, id: NftId, metadata: Vec, royalty: T::Balance) -> DispatchResult { let _sender = ensure_signed(origin)?; - Self::mint_token(owner, id, metadata)?; + Self::mint_token(owner, id, metadata, royalty)?; Ok(()) } @@ -135,7 +138,6 @@ decl_module! { let sender = ensure_signed(origin)?; ensure!(TokenCreatorOwner::::contains_key(nft_id), Error::::NftIdDoesNotExist); - let (_, owner) = Self::owner_of(nft_id); Self::set_bid_token(sender, nft_id, token_id, amount, dead_line)?; @@ -146,12 +148,12 @@ decl_module! { impl Module { /// Creates a new token in the system. - pub fn mint_token(owner: T::AccountId, id: NftId, metadata: Vec) -> DispatchResult { - ensure!(!Tokens::contains_key(id), Error::::TokenAlreadyExists); + pub fn mint_token(owner: T::AccountId, id: NftId, metadata: Vec, royalty: T::Balance) -> DispatchResult { + ensure!(!>::contains_key(id), Error::::TokenAlreadyExists); - let new_token = Erc721Token { id, metadata }; + let new_token = Erc721Token { id, metadata, royalty }; - ::insert(&id, new_token); + >::insert(&id, new_token); >::insert(&id, (owner.clone(), owner.clone())); let new_total = ::get().saturating_add(U256::one()); ::put(new_total); @@ -171,7 +173,7 @@ impl Module { let (_, owner) = Self::owner_of(id); ensure!(owner == from, Error::::NotOwner); // Update owner - TokenCreatorOwner::::mutate(id, |(creator, owner)| *owner = to.clone()); + TokenCreatorOwner::::mutate(id, |(_, owner)| *owner = to.clone()); Self::deposit_event(RawEvent::Transferred(from, to, id)); @@ -184,7 +186,7 @@ impl Module { let (_, owner) = Self::owner_of(id); ensure!(owner == from, Error::::NotOwner); - ::remove(&id); + >::remove(&id); >::remove(&id); let new_total = ::get().saturating_sub(U256::one()); ::put(new_total); @@ -209,7 +211,7 @@ impl Module { let now_timestamp = >::now(); if amount > ask_token && dead_line >=now_timestamp { - Self::execute_trade(); + Self::execute_trade(sender, id, token_id, amount); } else { >::insert(&sender, (amount, token_id, dead_line)); Self::deposit_event(RawEvent::SetBidAmount(id)); @@ -218,7 +220,14 @@ impl Module { Ok(()) } - fn execute_trade() -> DispatchResult { + fn execute_trade(sender: T::AccountId, id: NftId, token_id: T::AssetId, amount: T::Balance) -> DispatchResult { + let nft = Tokens::::get(id).ok_or(Error::::NftIdDoesNotExist)?; + let (creator, owner) = Self::owner_of(id); + if nft.royalty.is_zero() { + >::do_transfer(token_id, sender.clone(), creator, amount.saturating_mul(nft.royalty)); + >::do_transfer(token_id, sender, owner, amount.saturating_mul(T::Balance::one().saturating_sub(nft.royalty))); + TokenCreatorOwner::::mutate(id, |(_, owner)| *owner = sender.clone()); + } Ok(()) } } From a5bbaed24b278b54f1d5e2b921553c6be25d3e7d Mon Sep 17 00:00:00 2001 From: Ayush <> Date: Fri, 30 Apr 2021 20:00:23 +0530 Subject: [PATCH 06/12] Changed bid structure and added remove_bid functionality --- frame/social-nft/src/lib.rs | 47 +++++++++++++++++++++++++++++++++---- 1 file changed, 42 insertions(+), 5 deletions(-) diff --git a/frame/social-nft/src/lib.rs b/frame/social-nft/src/lib.rs index 92222c2f3..87d65fa02 100644 --- a/frame/social-nft/src/lib.rs +++ b/frame/social-nft/src/lib.rs @@ -26,6 +26,14 @@ pub struct Erc721Token { pub royalty: T::Balance, } +#[derive(PartialEq, Eq, Clone, Encode, Decode, RuntimeDebug)] +pub struct BidToken { + pub amount: T::Balance, + pub token_id: T::AssetId, + pub dead_line: T::Moment, + pub is_active: bool +} + pub trait Config: system::Config + pallet_assets::Config + pallet_timestamp::Config { type Event: From> + Into<::Event>; /// Some identifier for this token type, possibly the originating ethereum address. @@ -78,8 +86,9 @@ decl_storage! { pub TokenAskAmount get(fn ask_token): double_map hasher(opaque_blake2_256) NftId, hasher(twox_64_concat) T::AssetId => (T::Balance, T::AccountId); /// Maps tokenId to owner - pub TokenBidAmount get(fn bid_token): map hasher(opaque_blake2_256) T::AccountId => - (T::Balance, T::AssetId, T::Moment); + pub TokenBidAmount get(fn bid_token): double_map hasher(opaque_blake2_256) NftId, + hasher(twox_64_concat) T::AccountId => + Option>; } } @@ -141,6 +150,17 @@ decl_module! { Self::set_bid_token(sender, nft_id, token_id, amount, dead_line)?; + Ok(()) + } + + #[weight = 195_000_000] + pub fn remove_bid(origin, nft_id: NftId) -> DispatchResult { + let sender = ensure_signed(origin)?; + + ensure!(TokenCreatorOwner::::contains_key(nft_id), Error::::NftIdDoesNotExist); + + Self::remove_bid_token(sender, nft_id)?; + Ok(()) } } @@ -213,20 +233,37 @@ impl Module { if amount > ask_token && dead_line >=now_timestamp { Self::execute_trade(sender, id, token_id, amount); } else { - >::insert(&sender, (amount, token_id, dead_line)); + let bid = BidToken{ + amount, + token_id, + dead_line, + is_active: true + }; + >::insert(&id, &sender, bid); Self::deposit_event(RawEvent::SetBidAmount(id)); } Ok(()) } + pub fn remove_bid_token(sender: T::AccountId, id: NftId) -> DispatchResult { + ensure!(TokenBidAmount::::contains_key(id, sender.clone()), Error::::NftIdDoesNotExist); + TokenBidAmount::::mutate(id, &sender, |bid| + if let Some(b) = bid { + b.is_active = false + } + ); + + Ok(()) + } + fn execute_trade(sender: T::AccountId, id: NftId, token_id: T::AssetId, amount: T::Balance) -> DispatchResult { let nft = Tokens::::get(id).ok_or(Error::::NftIdDoesNotExist)?; let (creator, owner) = Self::owner_of(id); if nft.royalty.is_zero() { >::do_transfer(token_id, sender.clone(), creator, amount.saturating_mul(nft.royalty)); - >::do_transfer(token_id, sender, owner, amount.saturating_mul(T::Balance::one().saturating_sub(nft.royalty))); - TokenCreatorOwner::::mutate(id, |(_, owner)| *owner = sender.clone()); + >::do_transfer(token_id, sender.clone(), owner, amount.saturating_mul(T::Balance::one().saturating_sub(nft.royalty))); + TokenCreatorOwner::::mutate(id, |(_, owner)| *owner = sender); } Ok(()) } From 763bbf9d961487035b999c7bfa5fb231f1a6488a Mon Sep 17 00:00:00 2001 From: Ayush <> Date: Fri, 30 Apr 2021 20:08:02 +0530 Subject: [PATCH 07/12] Addressed PR coment --- frame/social-bridge/src/lib.rs | 15 +++++++-------- frame/social-nft/src/lib.rs | 22 +++++++++++----------- 2 files changed, 18 insertions(+), 19 deletions(-) diff --git a/frame/social-bridge/src/lib.rs b/frame/social-bridge/src/lib.rs index ef2df1672..991a81c1e 100644 --- a/frame/social-bridge/src/lib.rs +++ b/frame/social-bridge/src/lib.rs @@ -7,7 +7,6 @@ use frame_support::{ decl_error, decl_event, decl_module, dispatch::DispatchResult, ensure, }; use frame_system::{self as system, ensure_signed}; -use pallet_social_nft as erc721; use sp_arithmetic::traits::SaturatedConversion; use sp_core::U256; use sp_std::prelude::*; @@ -21,7 +20,7 @@ type BalanceOf = <::Currency as Currency<::AccountId>>::Balance; pub trait Config: - system::Config + bridge::Config + pallet_assets::Config + erc721::Config + system::Config + bridge::Config + pallet_assets::Config + pallet_social_nft::Config { type Event: From> + Into<::Event>; /// Specifies the origin check provided by the bridge for calls that can only be called by the bridge pallet @@ -100,14 +99,14 @@ decl_module! { >::transfer_fungible(dest_id, resource_id, recipient, U256::from(value.saturated_into::())) } - /// Transfer a non-fungible token (erc721) to a (whitelisted) destination chain. + /// Transfer a non-fungible token (pallet_social_nft) to a (whitelisted) destination chain. #[weight = 195_000_000] pub fn transfer_erc721(origin, recipient: Vec, token_id: U256, dest_id: bridge::ChainId) -> DispatchResult { let source = ensure_signed(origin)?; ensure!(>::chain_whitelisted(dest_id), Error::::InvalidTransfer); - match >::tokens(&token_id) { + match >::tokens(&token_id) { Some(token) => { - >::burn_token(source, token_id)?; + >::burn_token(source, token_id)?; let resource_id = T::Erc721Id::get(); let tid: &mut [u8] = &mut[0; 32]; token_id.to_big_endian(tid); @@ -137,11 +136,11 @@ decl_module! { Ok(()) } - /// Allows the bridge to issue new erc721 tokens + /// Allows the bridge to issue new pallet_social_nft tokens #[weight = 195_000_000] - pub fn mint_erc721(origin, recipient: T::AccountId, id: U256, metadata: Vec, royalty: T::Balance) -> DispatchResult { + pub fn mint_erc721(origin, recipient: T::AccountId, id: U256, metadata: Vec, royalty: T::Balance, r_id: ResourceId) -> DispatchResult { T::BridgeOrigin::ensure_origin(origin)?; - >::mint_token(recipient, id, metadata, royalty)?; + >::mint_token(recipient, id, metadata, royalty)?; Ok(()) } } diff --git a/frame/social-nft/src/lib.rs b/frame/social-nft/src/lib.rs index 87d65fa02..6c86627ab 100644 --- a/frame/social-nft/src/lib.rs +++ b/frame/social-nft/src/lib.rs @@ -77,7 +77,7 @@ decl_storage! { /// Maps tokenId to Erc721 object pub Tokens get(fn tokens): map hasher(opaque_blake2_256) NftId => Option>; /// Maps tokenId to owner - pub TokenCreatorOwner get(fn owner_of): map hasher(opaque_blake2_256) NftId => (T::AccountId, T::AccountId); + pub TokenCreatorAndOwner get(fn owner_of): map hasher(opaque_blake2_256) NftId => (T::AccountId, T::AccountId); /// Total number of tokens in existence pub TokenCount get(fn token_count): U256 = U256::zero(); /// Maximum token id @@ -122,7 +122,7 @@ decl_module! { pub fn burn(origin, id: NftId) -> DispatchResult { let _sender = ensure_signed(origin)?; - ensure!(TokenCreatorOwner::::contains_key(id), Error::::NftIdDoesNotExist); + ensure!(TokenCreatorAndOwner::::contains_key(id), Error::::NftIdDoesNotExist); let (_, owner) = Self::owner_of(id); Self::burn_token(owner, id)?; @@ -134,7 +134,7 @@ decl_module! { pub fn set_ask(origin, nft_id: NftId, token_id: T::AssetId, amount: T::Balance) -> DispatchResult { let sender = ensure_signed(origin)?; - ensure!(TokenCreatorOwner::::contains_key(nft_id), Error::::NftIdDoesNotExist); + ensure!(TokenCreatorAndOwner::::contains_key(nft_id), Error::::NftIdDoesNotExist); let (_, owner) = Self::owner_of(nft_id); ensure!(owner == sender, Error::::NotOwner); Self::set_ask_token(owner, nft_id, token_id, amount)?; @@ -146,7 +146,7 @@ decl_module! { pub fn set_bid(origin, nft_id: NftId, token_id: T::AssetId, amount: T::Balance, dead_line: T::Moment) -> DispatchResult { let sender = ensure_signed(origin)?; - ensure!(TokenCreatorOwner::::contains_key(nft_id), Error::::NftIdDoesNotExist); + ensure!(TokenCreatorAndOwner::::contains_key(nft_id), Error::::NftIdDoesNotExist); Self::set_bid_token(sender, nft_id, token_id, amount, dead_line)?; @@ -157,7 +157,7 @@ decl_module! { pub fn remove_bid(origin, nft_id: NftId) -> DispatchResult { let sender = ensure_signed(origin)?; - ensure!(TokenCreatorOwner::::contains_key(nft_id), Error::::NftIdDoesNotExist); + ensure!(TokenCreatorAndOwner::::contains_key(nft_id), Error::::NftIdDoesNotExist); Self::remove_bid_token(sender, nft_id)?; @@ -174,7 +174,7 @@ impl Module { let new_token = Erc721Token { id, metadata, royalty }; >::insert(&id, new_token); - >::insert(&id, (owner.clone(), owner.clone())); + >::insert(&id, (owner.clone(), owner.clone())); let new_total = ::get().saturating_add(U256::one()); ::put(new_total); if ::get() < id { @@ -189,11 +189,11 @@ impl Module { /// Modifies ownership of a token pub fn transfer_from(from: T::AccountId, to: T::AccountId, id: NftId) -> DispatchResult { // Check from is owner and token exists - ensure!(TokenCreatorOwner::::contains_key(id), Error::::NftIdDoesNotExist); + ensure!(TokenCreatorAndOwner::::contains_key(id), Error::::NftIdDoesNotExist); let (_, owner) = Self::owner_of(id); ensure!(owner == from, Error::::NotOwner); // Update owner - TokenCreatorOwner::::mutate(id, |(_, owner)| *owner = to.clone()); + TokenCreatorAndOwner::::mutate(id, |(_, owner)| *owner = to.clone()); Self::deposit_event(RawEvent::Transferred(from, to, id)); @@ -202,12 +202,12 @@ impl Module { /// Deletes a token from the system. pub fn burn_token(from: T::AccountId, id: NftId) -> DispatchResult { - ensure!(TokenCreatorOwner::::contains_key(id), Error::::NftIdDoesNotExist); + ensure!(TokenCreatorAndOwner::::contains_key(id), Error::::NftIdDoesNotExist); let (_, owner) = Self::owner_of(id); ensure!(owner == from, Error::::NotOwner); >::remove(&id); - >::remove(&id); + >::remove(&id); let new_total = ::get().saturating_sub(U256::one()); ::put(new_total); @@ -263,7 +263,7 @@ impl Module { if nft.royalty.is_zero() { >::do_transfer(token_id, sender.clone(), creator, amount.saturating_mul(nft.royalty)); >::do_transfer(token_id, sender.clone(), owner, amount.saturating_mul(T::Balance::one().saturating_sub(nft.royalty))); - TokenCreatorOwner::::mutate(id, |(_, owner)| *owner = sender); + TokenCreatorAndOwner::::mutate(id, |(_, owner)| *owner = sender); } Ok(()) } From 434129b6d0e97bf59ae8a2ba765ece0374dbea6a Mon Sep 17 00:00:00 2001 From: Ayush <> Date: Sat, 1 May 2021 19:19:41 +0530 Subject: [PATCH 08/12] Refactored test-cases according to latest changes --- frame/social-nft/src/lib.rs | 2 + frame/social-nft/src/mock.rs | 83 ++++++++++++++++++++++++++++------- frame/social-nft/src/tests.rs | 38 +++++++++------- 3 files changed, 90 insertions(+), 33 deletions(-) diff --git a/frame/social-nft/src/lib.rs b/frame/social-nft/src/lib.rs index 6c86627ab..77c79d88d 100644 --- a/frame/social-nft/src/lib.rs +++ b/frame/social-nft/src/lib.rs @@ -14,7 +14,9 @@ use sp_runtime::traits::{Zero, One}; use sp_runtime::{ traits::Saturating, }; +#[cfg(test)] mod mock; +#[cfg(test)] mod tests; type NftId = U256; diff --git a/frame/social-nft/src/mock.rs b/frame/social-nft/src/mock.rs index 502974611..227a73839 100644 --- a/frame/social-nft/src/mock.rs +++ b/frame/social-nft/src/mock.rs @@ -14,8 +14,8 @@ use crate::{self as erc721, Config}; use chainbridge as bridge; pub use pallet_balances as balances; -pub type Block = sp_runtime::generic::Block; -pub type UncheckedExtrinsic = sp_runtime::generic::UncheckedExtrinsic; +type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; +type Block = frame_system::mocking::MockBlock; frame_support::construct_runtime!( pub enum Test where @@ -25,16 +25,12 @@ frame_support::construct_runtime!( { System: system::{Module, Call, Event}, Balances: balances::{Module, Call, Storage, Config, Event}, + Assets: pallet_assets::{Module, Call, Storage, Event}, + Timestamp: pallet_timestamp::{Module, Call, Storage, Inherent}, Erc721: erc721::{Module, Call, Storage, Event}, } ); -pub const USER_A: u64 = 0x1; -pub const USER_B: u64 = 0x2; -pub const USER_C: u64 = 0x3; -pub const ENDOWED_BALANCE: u64 = 100_000_000; - - parameter_types! { pub const BlockHashCount: u64 = 250; pub BlockWeights: frame_system::limits::BlockWeights = @@ -83,6 +79,40 @@ impl pallet_balances::Config for Test { type WeightInfo = (); } +type Moment = u128; + +parameter_types! { + pub const MinimumPeriod: Moment = 5; + } +impl pallet_timestamp::Config for Test { + type Moment = Moment; + type OnTimestampSet = (); + type MinimumPeriod = MinimumPeriod; + type WeightInfo = (); +} + +parameter_types! { + pub const AssetDepositBase: u64 = 1; + pub const AssetDepositPerZombie: u64 = 1; + pub const StringLimit: u32 = 50; + pub const MetadataDepositBase: u64 = 1; + pub const MetadataDepositPerByte: u64 = 1; + } + +impl pallet_assets::Config for Test { + type Currency = Balances; + type Event = Event; + type Balance = u128; + type AssetId = u32; + type ForceOrigin = frame_system::EnsureRoot; + type AssetDepositBase = AssetDepositBase; + type AssetDepositPerZombie = AssetDepositPerZombie; + type StringLimit = StringLimit; + type MetadataDepositBase = MetadataDepositBase; + type MetadataDepositPerByte = MetadataDepositPerByte; + type WeightInfo = (); +} + parameter_types! { pub Erc721Id: bridge::ResourceId = bridge::derive_resource_id(1, &blake2_128(b"NFT")); } @@ -92,13 +122,34 @@ impl Config for Test { type Identifier = Erc721Id; } +pub const USER_A: u64 = 0x1; +pub const USER_B: u64 = 0x2; +pub const USER_C: u64 = 0x3; +pub const ENDOWED_BALANCE: u64 = 100_000_000; +pub const ROYALTY:u128 = 2; +pub const ASSET_ID:u32 = 1; +pub const ACCOUNT1:u64 = 1; +pub const ACCOUNT2:u64 = 2; +pub const ACCOUNT3:u64 = 3; +pub const MAX_ZOMBIES:u32 = 3; +pub const MIN_BALANCE:u128 = 1; +pub const TOKEN0:u64 = 10; +pub const TOKEN1:u64 = 11; +pub const FEE_TO:u64 = 12; +pub const ADDRESS0:u64 = 13; +pub const TREASURY:u64 = 14; +pub const INITIAL_SUPPLY: u128 = 1_000_000_000_000_000_000_0000; + pub fn new_test_ext() -> sp_io::TestExternalities { - GenesisConfig { - balances: Some(balances::GenesisConfig { - balances: vec![(USER_A, ENDOWED_BALANCE)], - }), - } - .build_storage() - .unwrap() - .into() + let mut t = frame_system::GenesisConfig::default().build_storage::().unwrap(); + pallet_balances::GenesisConfig:: { + balances: vec![(USER_A, ENDOWED_BALANCE)/*, (ACCOUNT1, ENDOWED_BALANCE), (ACCOUNT2, ENDOWED_BALANCE)*/], + }.assimilate_storage(&mut t).unwrap(); + +/* pallet_assets::GenesisConfig:: { + assets: vec![(ASSET_ID, ACCOUNT1, ACCOUNT1, MAX_ZOMBIES, MIN_BALANCE)], + accounts: vec![(ASSET_ID, ACCOUNT1, INITIAL_SUPPLY), (ASSET_ID, TREASURY, 0u128)], + }.assimilate_storage(&mut t).unwrap();*/ + + t.into() } diff --git a/frame/social-nft/src/tests.rs b/frame/social-nft/src/tests.rs index 23f11476f..0f69c438f 100644 --- a/frame/social-nft/src/tests.rs +++ b/frame/social-nft/src/tests.rs @@ -1,6 +1,6 @@ #![cfg(test)] -use super::mock::{new_test_ext, Erc721, Origin, Test, USER_A, USER_B, USER_C}; +use super::mock::{new_test_ext, Erc721, Origin, Test, USER_A, USER_B, USER_C, ROYALTY}; use super::*; use frame_support::{assert_noop, assert_ok}; use sp_core::U256; @@ -17,19 +17,21 @@ fn mint_burn_tokens() { Origin::signed(1), // Origin::root(), USER_A, id_a, - metadata_a.clone() + metadata_a.clone(), + ROYALTY )); assert_eq!( Erc721::tokens(id_a).unwrap(), Erc721Token { id: id_a, - metadata: metadata_a.clone() + metadata: metadata_a.clone(), + royalty: ROYALTY } ); assert_eq!(Erc721::token_count(), 1.into()); assert_eq!(Erc721::max_token_id(), 1.into()); assert_noop!( - Erc721::mint(Origin::signed(1), USER_A, id_a, metadata_a), // Erc721::mint(Origin::root(), USER_A, id_a, metadata_a), + Erc721::mint(Origin::signed(1), USER_A, id_a, metadata_a, ROYALTY), // Erc721::mint(Origin::root(), USER_A, id_a, metadata_a), Error::::TokenAlreadyExists ); @@ -37,33 +39,35 @@ fn mint_burn_tokens() { Origin::signed(1), // Origin::root(), USER_A, id_b, - metadata_b.clone() + metadata_b.clone(), + ROYALTY )); assert_eq!( Erc721::tokens(id_b).unwrap(), Erc721Token { id: id_b, - metadata: metadata_b.clone() + metadata: metadata_b.clone(), + royalty: ROYALTY } ); assert_eq!(Erc721::token_count(), 2.into()); assert_eq!(Erc721::max_token_id(), 2.into()); assert_noop!( - Erc721::mint(Origin::signed(1), USER_A, id_b, metadata_b), // Erc721::mint(Origin::root(), USER_A, id_b, metadata_b), + Erc721::mint(Origin::signed(1), USER_A, id_b, metadata_b, ROYALTY), // Erc721::mint(Origin::root(), USER_A, id_b, metadata_b), Error::::TokenAlreadyExists ); assert_ok!(Erc721::burn(Origin::signed(1), id_a)); // assert_ok!(Erc721::burn(Origin::root(), id_a)); assert_eq!(Erc721::token_count(), 1.into()); assert_eq!(Erc721::max_token_id(), 2.into()); - assert!(!::contains_key(&id_a)); - assert!(!>::contains_key(&id_a)); + assert!(!>::contains_key(&id_a)); + assert!(!>::contains_key(&id_a)); assert_ok!(Erc721::burn(Origin::signed(1), id_b)); // assert_ok!(Erc721::burn(Origin::root(), id_b)); assert_eq!(Erc721::token_count(), 0.into()); assert_eq!(Erc721::max_token_id(), 2.into()); - assert!(!::contains_key(&id_b)); - assert!(!>::contains_key(&id_b)); + assert!(!>::contains_key(&id_b)); + assert!(!>::contains_key(&id_b)); }) } @@ -75,19 +79,19 @@ fn transfer_tokens() { let metadata_a: Vec = vec![1, 2, 3]; let metadata_b: Vec = vec![4, 5, 6]; - assert_ok!(Erc721::mint(Origin::signed(1), USER_A, id_a, metadata_a)); // assert_ok!(Erc721::mint(Origin::root(), USER_A, id_a, metadata_a)); - assert_ok!(Erc721::mint(Origin::signed(1), USER_A, id_b, metadata_b)); // assert_ok!(Erc721::mint(Origin::root(), USER_A, id_b, metadata_b)); + assert_ok!(Erc721::mint(Origin::signed(1), USER_A, id_a, metadata_a, ROYALTY)); // assert_ok!(Erc721::mint(Origin::root(), USER_A, id_a, metadata_a)); + assert_ok!(Erc721::mint(Origin::signed(1), USER_A, id_b, metadata_b, ROYALTY)); // assert_ok!(Erc721::mint(Origin::root(), USER_A, id_b, metadata_b)); assert_ok!(Erc721::transfer(Origin::signed(USER_A), USER_B, id_a)); - assert_eq!(Erc721::owner_of(id_a).unwrap(), USER_B); + assert_eq!(Erc721::owner_of(id_a).1, USER_B); assert_ok!(Erc721::transfer(Origin::signed(USER_A), USER_C, id_b)); - assert_eq!(Erc721::owner_of(id_b).unwrap(), USER_C); + assert_eq!(Erc721::owner_of(id_b).1, USER_C); assert_ok!(Erc721::transfer(Origin::signed(USER_B), USER_A, id_a)); - assert_eq!(Erc721::owner_of(id_a).unwrap(), USER_A); + assert_eq!(Erc721::owner_of(id_a).1, USER_A); assert_ok!(Erc721::transfer(Origin::signed(USER_C), USER_A, id_b)); - assert_eq!(Erc721::owner_of(id_b).unwrap(), USER_A); + assert_eq!(Erc721::owner_of(id_b).1, USER_A); }) } From 052837884f9bfa56c8dce2ab35778cf55cc9c8a2 Mon Sep 17 00:00:00 2001 From: Ayush <> Date: Sat, 1 May 2021 20:28:05 +0530 Subject: [PATCH 09/12] Refactor code and added test-cases for set-ask --- frame/social-nft/src/mock.rs | 4 +- frame/social-nft/src/tests.rs | 87 ++++++++++++++++++++++++----------- 2 files changed, 62 insertions(+), 29 deletions(-) diff --git a/frame/social-nft/src/mock.rs b/frame/social-nft/src/mock.rs index 227a73839..5b9824803 100644 --- a/frame/social-nft/src/mock.rs +++ b/frame/social-nft/src/mock.rs @@ -10,7 +10,7 @@ use sp_runtime::{ BuildStorage, }; -use crate::{self as erc721, Config}; +use crate::{self as pallet_social_nft, Config}; use chainbridge as bridge; pub use pallet_balances as balances; @@ -27,7 +27,7 @@ frame_support::construct_runtime!( Balances: balances::{Module, Call, Storage, Config, Event}, Assets: pallet_assets::{Module, Call, Storage, Event}, Timestamp: pallet_timestamp::{Module, Call, Storage, Inherent}, - Erc721: erc721::{Module, Call, Storage, Event}, + Social_NFT: pallet_social_nft::{Module, Call, Storage, Event}, } ); diff --git a/frame/social-nft/src/tests.rs b/frame/social-nft/src/tests.rs index 0f69c438f..2df27b14e 100644 --- a/frame/social-nft/src/tests.rs +++ b/frame/social-nft/src/tests.rs @@ -1,6 +1,6 @@ #![cfg(test)] -use super::mock::{new_test_ext, Erc721, Origin, Test, USER_A, USER_B, USER_C, ROYALTY}; +use super::mock::{new_test_ext, Social_NFT, Origin, Test, USER_A, USER_B, USER_C, ROYALTY}; use super::*; use frame_support::{assert_noop, assert_ok}; use sp_core::U256; @@ -13,7 +13,7 @@ fn mint_burn_tokens() { let metadata_a: Vec = vec![1, 2, 3]; let metadata_b: Vec = vec![4, 5, 6]; - assert_ok!(Erc721::mint( + assert_ok!(Social_NFT::mint( Origin::signed(1), // Origin::root(), USER_A, id_a, @@ -21,21 +21,21 @@ fn mint_burn_tokens() { ROYALTY )); assert_eq!( - Erc721::tokens(id_a).unwrap(), + Social_NFT::tokens(id_a).unwrap(), Erc721Token { id: id_a, metadata: metadata_a.clone(), royalty: ROYALTY } ); - assert_eq!(Erc721::token_count(), 1.into()); - assert_eq!(Erc721::max_token_id(), 1.into()); + assert_eq!(Social_NFT::token_count(), 1.into()); + assert_eq!(Social_NFT::max_token_id(), 1.into()); assert_noop!( - Erc721::mint(Origin::signed(1), USER_A, id_a, metadata_a, ROYALTY), // Erc721::mint(Origin::root(), USER_A, id_a, metadata_a), + Social_NFT::mint(Origin::signed(1), USER_A, id_a, metadata_a, ROYALTY), // Social_NFT::mint(Origin::root(), USER_A, id_a, metadata_a), Error::::TokenAlreadyExists ); - assert_ok!(Erc721::mint( + assert_ok!(Social_NFT::mint( Origin::signed(1), // Origin::root(), USER_A, id_b, @@ -43,29 +43,29 @@ fn mint_burn_tokens() { ROYALTY )); assert_eq!( - Erc721::tokens(id_b).unwrap(), + Social_NFT::tokens(id_b).unwrap(), Erc721Token { id: id_b, metadata: metadata_b.clone(), royalty: ROYALTY } ); - assert_eq!(Erc721::token_count(), 2.into()); - assert_eq!(Erc721::max_token_id(), 2.into()); + assert_eq!(Social_NFT::token_count(), 2.into()); + assert_eq!(Social_NFT::max_token_id(), 2.into()); assert_noop!( - Erc721::mint(Origin::signed(1), USER_A, id_b, metadata_b, ROYALTY), // Erc721::mint(Origin::root(), USER_A, id_b, metadata_b), + Social_NFT::mint(Origin::signed(1), USER_A, id_b, metadata_b, ROYALTY), // Social_NFT::mint(Origin::root(), USER_A, id_b, metadata_b), Error::::TokenAlreadyExists ); - assert_ok!(Erc721::burn(Origin::signed(1), id_a)); // assert_ok!(Erc721::burn(Origin::root(), id_a)); - assert_eq!(Erc721::token_count(), 1.into()); - assert_eq!(Erc721::max_token_id(), 2.into()); + assert_ok!(Social_NFT::burn(Origin::signed(1), id_a)); // assert_ok!(Social_NFT::burn(Origin::root(), id_a)); + assert_eq!(Social_NFT::token_count(), 1.into()); + assert_eq!(Social_NFT::max_token_id(), 2.into()); assert!(!>::contains_key(&id_a)); assert!(!>::contains_key(&id_a)); - assert_ok!(Erc721::burn(Origin::signed(1), id_b)); // assert_ok!(Erc721::burn(Origin::root(), id_b)); - assert_eq!(Erc721::token_count(), 0.into()); - assert_eq!(Erc721::max_token_id(), 2.into()); + assert_ok!(Social_NFT::burn(Origin::signed(1), id_b)); // assert_ok!(Social_NFT::burn(Origin::root(), id_b)); + assert_eq!(Social_NFT::token_count(), 0.into()); + assert_eq!(Social_NFT::max_token_id(), 2.into()); assert!(!>::contains_key(&id_b)); assert!(!>::contains_key(&id_b)); }) @@ -79,19 +79,52 @@ fn transfer_tokens() { let metadata_a: Vec = vec![1, 2, 3]; let metadata_b: Vec = vec![4, 5, 6]; - assert_ok!(Erc721::mint(Origin::signed(1), USER_A, id_a, metadata_a, ROYALTY)); // assert_ok!(Erc721::mint(Origin::root(), USER_A, id_a, metadata_a)); - assert_ok!(Erc721::mint(Origin::signed(1), USER_A, id_b, metadata_b, ROYALTY)); // assert_ok!(Erc721::mint(Origin::root(), USER_A, id_b, metadata_b)); + assert_ok!(Social_NFT::mint(Origin::signed(1), USER_A, id_a, metadata_a, ROYALTY)); // assert_ok!(Social_NFT::mint(Origin::root(), USER_A, id_a, metadata_a)); + assert_ok!(Social_NFT::mint(Origin::signed(1), USER_A, id_b, metadata_b, ROYALTY)); // assert_ok!(Social_NFT::mint(Origin::root(), USER_A, id_b, metadata_b)); - assert_ok!(Erc721::transfer(Origin::signed(USER_A), USER_B, id_a)); - assert_eq!(Erc721::owner_of(id_a).1, USER_B); + assert_ok!(Social_NFT::transfer(Origin::signed(USER_A), USER_B, id_a)); + assert_eq!(Social_NFT::owner_of(id_a).1, USER_B); - assert_ok!(Erc721::transfer(Origin::signed(USER_A), USER_C, id_b)); - assert_eq!(Erc721::owner_of(id_b).1, USER_C); + assert_ok!(Social_NFT::transfer(Origin::signed(USER_A), USER_C, id_b)); + assert_eq!(Social_NFT::owner_of(id_b).1, USER_C); - assert_ok!(Erc721::transfer(Origin::signed(USER_B), USER_A, id_a)); - assert_eq!(Erc721::owner_of(id_a).1, USER_A); + assert_ok!(Social_NFT::transfer(Origin::signed(USER_B), USER_A, id_a)); + assert_eq!(Social_NFT::owner_of(id_a).1, USER_A); - assert_ok!(Erc721::transfer(Origin::signed(USER_C), USER_A, id_b)); - assert_eq!(Erc721::owner_of(id_b).1, USER_A); + assert_ok!(Social_NFT::transfer(Origin::signed(USER_C), USER_A, id_b)); + assert_eq!(Social_NFT::owner_of(id_b).1, USER_A); }) } + +#[test] +fn set_ask_tokens() { + new_test_ext().execute_with(|| { + let id_a: U256 = 1.into(); + let id_b: U256 = 2.into(); + let metadata_a: Vec = vec![1, 2, 3]; + let metadata_b: Vec = vec![4, 5, 6]; + assert_noop!( + Social_NFT::set_ask(Origin::signed(1), id_a, 1, 1), + Error::::NftIdDoesNotExist + ); + + assert_ok!(Social_NFT::mint( + Origin::signed(1), // Origin::root(), + USER_A, + id_a, + metadata_a.clone(), + ROYALTY + )); + + assert_noop!( + Social_NFT::set_ask(Origin::signed(11), id_a, 1, 1), + Error::::NotOwner + ); + + assert_ok!( + Social_NFT::set_ask(Origin::signed(USER_A), id_a, 1, 1) + ); + + assert!(>::contains_key(id_a, 1)); + }) +} From dd31290b9b2aa4dd97ebdd5c00e101a8226f089b Mon Sep 17 00:00:00 2001 From: Ayush <> Date: Sat, 1 May 2021 20:39:55 +0530 Subject: [PATCH 10/12] Added more test-cases for social-nft --- frame/social-nft/src/lib.rs | 2 +- frame/social-nft/src/mock.rs | 23 +----- frame/social-nft/src/tests.rs | 138 ++++++++++++++++++++++++++-------- 3 files changed, 109 insertions(+), 54 deletions(-) diff --git a/frame/social-nft/src/lib.rs b/frame/social-nft/src/lib.rs index 77c79d88d..222a0f1cd 100644 --- a/frame/social-nft/src/lib.rs +++ b/frame/social-nft/src/lib.rs @@ -229,7 +229,7 @@ impl Module { let (ask_token, _) = TokenAskAmount::::get(id, token_id); - ensure!(ask_token.is_zero(), Error::::NotForSale); + ensure!(!ask_token.is_zero(), Error::::NotForSale); let now_timestamp = >::now(); if amount > ask_token && dead_line >=now_timestamp { diff --git a/frame/social-nft/src/mock.rs b/frame/social-nft/src/mock.rs index 5b9824803..add216e81 100644 --- a/frame/social-nft/src/mock.rs +++ b/frame/social-nft/src/mock.rs @@ -6,7 +6,7 @@ use sp_core::hashing::blake2_128; use sp_core::H256; use sp_runtime::{ testing::Header, - traits::{BlakeTwo256, Block as BlockT, IdentityLookup}, + traits::{BlakeTwo256, IdentityLookup}, BuildStorage, }; @@ -27,7 +27,7 @@ frame_support::construct_runtime!( Balances: balances::{Module, Call, Storage, Config, Event}, Assets: pallet_assets::{Module, Call, Storage, Event}, Timestamp: pallet_timestamp::{Module, Call, Storage, Inherent}, - Social_NFT: pallet_social_nft::{Module, Call, Storage, Event}, + SocialNft: pallet_social_nft::{Module, Call, Storage, Event}, } ); @@ -127,29 +127,12 @@ pub const USER_B: u64 = 0x2; pub const USER_C: u64 = 0x3; pub const ENDOWED_BALANCE: u64 = 100_000_000; pub const ROYALTY:u128 = 2; -pub const ASSET_ID:u32 = 1; -pub const ACCOUNT1:u64 = 1; -pub const ACCOUNT2:u64 = 2; -pub const ACCOUNT3:u64 = 3; -pub const MAX_ZOMBIES:u32 = 3; -pub const MIN_BALANCE:u128 = 1; -pub const TOKEN0:u64 = 10; -pub const TOKEN1:u64 = 11; -pub const FEE_TO:u64 = 12; -pub const ADDRESS0:u64 = 13; -pub const TREASURY:u64 = 14; -pub const INITIAL_SUPPLY: u128 = 1_000_000_000_000_000_000_0000; pub fn new_test_ext() -> sp_io::TestExternalities { let mut t = frame_system::GenesisConfig::default().build_storage::().unwrap(); pallet_balances::GenesisConfig:: { - balances: vec![(USER_A, ENDOWED_BALANCE)/*, (ACCOUNT1, ENDOWED_BALANCE), (ACCOUNT2, ENDOWED_BALANCE)*/], + balances: vec![(USER_A, ENDOWED_BALANCE)], }.assimilate_storage(&mut t).unwrap(); -/* pallet_assets::GenesisConfig:: { - assets: vec![(ASSET_ID, ACCOUNT1, ACCOUNT1, MAX_ZOMBIES, MIN_BALANCE)], - accounts: vec![(ASSET_ID, ACCOUNT1, INITIAL_SUPPLY), (ASSET_ID, TREASURY, 0u128)], - }.assimilate_storage(&mut t).unwrap();*/ - t.into() } diff --git a/frame/social-nft/src/tests.rs b/frame/social-nft/src/tests.rs index 2df27b14e..8741d9c98 100644 --- a/frame/social-nft/src/tests.rs +++ b/frame/social-nft/src/tests.rs @@ -1,6 +1,6 @@ #![cfg(test)] -use super::mock::{new_test_ext, Social_NFT, Origin, Test, USER_A, USER_B, USER_C, ROYALTY}; +use super::mock::{new_test_ext, SocialNft, Origin, Test, USER_A, USER_B, USER_C, ROYALTY}; use super::*; use frame_support::{assert_noop, assert_ok}; use sp_core::U256; @@ -13,7 +13,7 @@ fn mint_burn_tokens() { let metadata_a: Vec = vec![1, 2, 3]; let metadata_b: Vec = vec![4, 5, 6]; - assert_ok!(Social_NFT::mint( + assert_ok!(SocialNft::mint( Origin::signed(1), // Origin::root(), USER_A, id_a, @@ -21,21 +21,21 @@ fn mint_burn_tokens() { ROYALTY )); assert_eq!( - Social_NFT::tokens(id_a).unwrap(), + SocialNft::tokens(id_a).unwrap(), Erc721Token { id: id_a, metadata: metadata_a.clone(), royalty: ROYALTY } ); - assert_eq!(Social_NFT::token_count(), 1.into()); - assert_eq!(Social_NFT::max_token_id(), 1.into()); + assert_eq!(SocialNft::token_count(), 1.into()); + assert_eq!(SocialNft::max_token_id(), 1.into()); assert_noop!( - Social_NFT::mint(Origin::signed(1), USER_A, id_a, metadata_a, ROYALTY), // Social_NFT::mint(Origin::root(), USER_A, id_a, metadata_a), + SocialNft::mint(Origin::signed(1), USER_A, id_a, metadata_a, ROYALTY), // SocialNft::mint(Origin::root(), USER_A, id_a, metadata_a), Error::::TokenAlreadyExists ); - assert_ok!(Social_NFT::mint( + assert_ok!(SocialNft::mint( Origin::signed(1), // Origin::root(), USER_A, id_b, @@ -43,29 +43,29 @@ fn mint_burn_tokens() { ROYALTY )); assert_eq!( - Social_NFT::tokens(id_b).unwrap(), + SocialNft::tokens(id_b).unwrap(), Erc721Token { id: id_b, metadata: metadata_b.clone(), royalty: ROYALTY } ); - assert_eq!(Social_NFT::token_count(), 2.into()); - assert_eq!(Social_NFT::max_token_id(), 2.into()); + assert_eq!(SocialNft::token_count(), 2.into()); + assert_eq!(SocialNft::max_token_id(), 2.into()); assert_noop!( - Social_NFT::mint(Origin::signed(1), USER_A, id_b, metadata_b, ROYALTY), // Social_NFT::mint(Origin::root(), USER_A, id_b, metadata_b), + SocialNft::mint(Origin::signed(1), USER_A, id_b, metadata_b, ROYALTY), // SocialNft::mint(Origin::root(), USER_A, id_b, metadata_b), Error::::TokenAlreadyExists ); - assert_ok!(Social_NFT::burn(Origin::signed(1), id_a)); // assert_ok!(Social_NFT::burn(Origin::root(), id_a)); - assert_eq!(Social_NFT::token_count(), 1.into()); - assert_eq!(Social_NFT::max_token_id(), 2.into()); + assert_ok!(SocialNft::burn(Origin::signed(1), id_a)); // assert_ok!(SocialNft::burn(Origin::root(), id_a)); + assert_eq!(SocialNft::token_count(), 1.into()); + assert_eq!(SocialNft::max_token_id(), 2.into()); assert!(!>::contains_key(&id_a)); assert!(!>::contains_key(&id_a)); - assert_ok!(Social_NFT::burn(Origin::signed(1), id_b)); // assert_ok!(Social_NFT::burn(Origin::root(), id_b)); - assert_eq!(Social_NFT::token_count(), 0.into()); - assert_eq!(Social_NFT::max_token_id(), 2.into()); + assert_ok!(SocialNft::burn(Origin::signed(1), id_b)); // assert_ok!(SocialNft::burn(Origin::root(), id_b)); + assert_eq!(SocialNft::token_count(), 0.into()); + assert_eq!(SocialNft::max_token_id(), 2.into()); assert!(!>::contains_key(&id_b)); assert!(!>::contains_key(&id_b)); }) @@ -79,20 +79,20 @@ fn transfer_tokens() { let metadata_a: Vec = vec![1, 2, 3]; let metadata_b: Vec = vec![4, 5, 6]; - assert_ok!(Social_NFT::mint(Origin::signed(1), USER_A, id_a, metadata_a, ROYALTY)); // assert_ok!(Social_NFT::mint(Origin::root(), USER_A, id_a, metadata_a)); - assert_ok!(Social_NFT::mint(Origin::signed(1), USER_A, id_b, metadata_b, ROYALTY)); // assert_ok!(Social_NFT::mint(Origin::root(), USER_A, id_b, metadata_b)); + assert_ok!(SocialNft::mint(Origin::signed(1), USER_A, id_a, metadata_a, ROYALTY)); // assert_ok!(SocialNft::mint(Origin::root(), USER_A, id_a, metadata_a)); + assert_ok!(SocialNft::mint(Origin::signed(1), USER_A, id_b, metadata_b, ROYALTY)); // assert_ok!(SocialNft::mint(Origin::root(), USER_A, id_b, metadata_b)); - assert_ok!(Social_NFT::transfer(Origin::signed(USER_A), USER_B, id_a)); - assert_eq!(Social_NFT::owner_of(id_a).1, USER_B); + assert_ok!(SocialNft::transfer(Origin::signed(USER_A), USER_B, id_a)); + assert_eq!(SocialNft::owner_of(id_a).1, USER_B); - assert_ok!(Social_NFT::transfer(Origin::signed(USER_A), USER_C, id_b)); - assert_eq!(Social_NFT::owner_of(id_b).1, USER_C); + assert_ok!(SocialNft::transfer(Origin::signed(USER_A), USER_C, id_b)); + assert_eq!(SocialNft::owner_of(id_b).1, USER_C); - assert_ok!(Social_NFT::transfer(Origin::signed(USER_B), USER_A, id_a)); - assert_eq!(Social_NFT::owner_of(id_a).1, USER_A); + assert_ok!(SocialNft::transfer(Origin::signed(USER_B), USER_A, id_a)); + assert_eq!(SocialNft::owner_of(id_a).1, USER_A); - assert_ok!(Social_NFT::transfer(Origin::signed(USER_C), USER_A, id_b)); - assert_eq!(Social_NFT::owner_of(id_b).1, USER_A); + assert_ok!(SocialNft::transfer(Origin::signed(USER_C), USER_A, id_b)); + assert_eq!(SocialNft::owner_of(id_b).1, USER_A); }) } @@ -100,15 +100,13 @@ fn transfer_tokens() { fn set_ask_tokens() { new_test_ext().execute_with(|| { let id_a: U256 = 1.into(); - let id_b: U256 = 2.into(); let metadata_a: Vec = vec![1, 2, 3]; - let metadata_b: Vec = vec![4, 5, 6]; assert_noop!( - Social_NFT::set_ask(Origin::signed(1), id_a, 1, 1), + SocialNft::set_ask(Origin::signed(1), id_a, 1, 1), Error::::NftIdDoesNotExist ); - assert_ok!(Social_NFT::mint( + assert_ok!(SocialNft::mint( Origin::signed(1), // Origin::root(), USER_A, id_a, @@ -117,14 +115,88 @@ fn set_ask_tokens() { )); assert_noop!( - Social_NFT::set_ask(Origin::signed(11), id_a, 1, 1), + SocialNft::set_ask(Origin::signed(11), id_a, 1, 1), Error::::NotOwner ); assert_ok!( - Social_NFT::set_ask(Origin::signed(USER_A), id_a, 1, 1) + SocialNft::set_ask(Origin::signed(USER_A), id_a, 1, 1) ); assert!(>::contains_key(id_a, 1)); }) } + +#[test] +fn set_bid_tokens() { + new_test_ext().execute_with(|| { + let id_a: U256 = 1.into(); + let metadata_a: Vec = vec![1, 2, 3]; + assert_noop!( + SocialNft::set_bid(Origin::signed(1), id_a, 1, 1, 1), + Error::::NftIdDoesNotExist + ); + + assert_ok!(SocialNft::mint( + Origin::signed(1), // Origin::root(), + USER_A, + id_a, + metadata_a.clone(), + ROYALTY + )); + + assert_ok!( + SocialNft::set_ask(Origin::signed(USER_A), id_a, 1, 0) + ); + + assert_noop!( + SocialNft::set_bid(Origin::signed(USER_A), id_a, 1, 1, 1), + Error::::NotForSale + ); + + assert_ok!( + SocialNft::set_ask(Origin::signed(USER_A), id_a, 1, 1) + ); + + assert_ok!( + SocialNft::set_bid(Origin::signed(USER_A), id_a, 1, 1, 1) + ); + + assert!(>::contains_key(id_a, 1)); + }) +} + +#[test] +fn remove_bid_tokens() { + new_test_ext().execute_with(|| { + let id_a: U256 = 1.into(); + let metadata_a: Vec = vec![1, 2, 3]; + + assert_noop!( + SocialNft::remove_bid(Origin::signed(1), id_a), + Error::::NftIdDoesNotExist + ); + + assert_ok!(SocialNft::mint( + Origin::signed(1), // Origin::root(), + USER_A, + id_a, + metadata_a.clone(), + ROYALTY + )); + + assert_ok!( + SocialNft::set_ask(Origin::signed(USER_A), id_a, 1, 1) + ); + + assert_ok!( + SocialNft::set_bid(Origin::signed(USER_A), id_a, 1, 1, 1) + ); + + assert_ok!( + SocialNft::remove_bid(Origin::signed(1), id_a), + ); + + assert!(!SocialNft::bid_token(id_a, 1).unwrap().is_active); + }) +} From da758d10ee775ea2765b7a904fad8cd7a9598d7b Mon Sep 17 00:00:00 2001 From: Andrey Orlov Date: Mon, 3 May 2021 14:06:52 +0400 Subject: [PATCH 11/12] Update tests of pallet-social-swap2 --- frame/social-swap2/src/lib.rs | 13 ++++++++----- frame/social-swap2/src/tests.rs | 17 +++++++++-------- 2 files changed, 17 insertions(+), 13 deletions(-) diff --git a/frame/social-swap2/src/lib.rs b/frame/social-swap2/src/lib.rs index 5336c9aba..bee1e299a 100644 --- a/frame/social-swap2/src/lib.rs +++ b/frame/social-swap2/src/lib.rs @@ -116,17 +116,20 @@ decl_module! { let fee_on = Self::mint_fee(reserve0, reserve1)?; let total_supply = T::FungibleToken::total_supply(&social_token_id); let liquidity = if total_supply == 0u32.into() { - let min_liquidity = T::MinimumLiquidity::get().saturated_into::().saturated_into(); - let liquidity = amount0 + let min_liquidity = T::MinimumLiquidity::get().saturated_into::().saturated_into(); + amount0 .saturating_mul(amount1) .integer_sqrt() - .saturating_sub(min_liquidity); - T::FungibleToken::issue(&social_token_id, &Self::address0(), min_liquidity)?; - liquidity + .saturating_sub(min_liquidity) } else { (amount0.saturating_mul(total_supply) / reserve0).min(amount1.saturating_mul(total_supply) / reserve1) }; ensure!(liquidity > 0u32.into(), Error::::InsufficientLiquidityMinted); + + if total_supply == 0u32.into() { + let min_liquidity = T::MinimumLiquidity::get().saturated_into::().saturated_into(); + T::FungibleToken::issue(&social_token_id, &Self::address0(), min_liquidity)?; + } T::FungibleToken::issue(&social_token_id, &to, liquidity)?; let _ = Self::update(balance0, balance1, reserve0, reserve1); diff --git a/frame/social-swap2/src/tests.rs b/frame/social-swap2/src/tests.rs index d8cec625a..f62482c35 100644 --- a/frame/social-swap2/src/tests.rs +++ b/frame/social-swap2/src/tests.rs @@ -73,14 +73,15 @@ fn test_mint_should_work() { #[test] fn test_burn_should_not_work() { - new_test_ext().execute_with(|| { - - assert_ne!(SocialSwap2::mint( - Origin::signed(ACCOUNT1), - ACCOUNT3 - ),Ok(())); - - }); + new_test_ext().execute_with(|| { + assert_noop!( + SocialSwap2::mint( + Origin::signed(ACCOUNT1), + ACCOUNT3 + ), + Error::::InsufficientLiquidityMinted + ); + }); } #[test] From 8362c3f4ab86b546446516362b8671362d4a9423 Mon Sep 17 00:00:00 2001 From: Andrey Orlov Date: Mon, 3 May 2021 16:38:40 +0400 Subject: [PATCH 12/12] Add workers/social-tokens-distributor --- workers/social-tokens-distributor/README.md | 16 + .../config/types.json | 89 +++ .../social-tokens-distributor/package.json | 10 + .../social-tokens-distributor/src/index.ts | 106 +++ .../social-tokens-distributor/tsconfig.json | 12 + workers/social-tokens-distributor/yarn.lock | 637 ++++++++++++++++++ 6 files changed, 870 insertions(+) create mode 100644 workers/social-tokens-distributor/README.md create mode 100644 workers/social-tokens-distributor/config/types.json create mode 100644 workers/social-tokens-distributor/package.json create mode 100644 workers/social-tokens-distributor/src/index.ts create mode 100644 workers/social-tokens-distributor/tsconfig.json create mode 100644 workers/social-tokens-distributor/yarn.lock diff --git a/workers/social-tokens-distributor/README.md b/workers/social-tokens-distributor/README.md new file mode 100644 index 000000000..45a10f944 --- /dev/null +++ b/workers/social-tokens-distributor/README.md @@ -0,0 +1,16 @@ +# social-tokens-distributor + +## Build + +```bash +yarn +tsc +``` + +## Running + +```bash +export WS_URL="ws://127.0.0.1:9944" +export PHRASE="0xe5be9a5092b81bca64be81d212e7f2f9eba183bb7a90954f7b76361f6edb5c0a" # Secret seed of //Alice +node dist/index.js +``` diff --git a/workers/social-tokens-distributor/config/types.json b/workers/social-tokens-distributor/config/types.json new file mode 100644 index 000000000..b84e45ff2 --- /dev/null +++ b/workers/social-tokens-distributor/config/types.json @@ -0,0 +1,89 @@ +{ + "AttributeTransaction": { + "signature": "Signature", + "name": "Vec", + "value": "Vec", + "validity": "u32", + "signer": "AccountId", + "identity": "AccountId" + }, + "Attribute": { + "name": "Vec", + "value": "Vec", + "validity": "BlockNumber", + "creation": "Moment", + "nonce": "u64" + }, + "SwapId": "u64", + "Swap": { + "token_id": "TokenId", + "swap_token": "TokenId", + "account": "AccountId" + }, + "AssetId": "u32", + "SocialTokenBalance": "u128", + "RegistrarIndex": "u32", + "Judgement": { + "_enum": [ + "Requested", + "Approved" + ] + }, + "JudgementItem": "(RegistrarIndex, Judgement)", + "Registration": { + "judgements": "Vec", + "account_id": "AccountId" + }, + "Bloom": "H256", + "Log": { + "address": "H160", + "topics": "Vec", + "data": "Bytes" + }, + "Receipt": { + "state_root": "H256", + "used_gas": "U256", + "logs_bloom": "Bloom", + "logs": "Vec" + }, + "TransactionAction": { + "_enum": { + "Call": "H160", + "Create": "Null" + } + }, + "TransactionRecoveryId": "u64", + "TransactionSignature": { + "v": "TransactionRecoveryId", + "r": "H256", + "s": "H256" + }, + "Transaction": { + "nonce": "U256", + "gas_price": "U256", + "gas_limit": "U256", + "action": "TransactionAction", + "value": "U256", + "input": "Bytes", + "signature": "TransactionSignature" + }, + "TransactionStatus": { + "transaction_hash": "H256", + "transaction_index": "u32", + "from": "H160", + "to": "Option", + "contract_address": "Option", + "logs": "Vec", + "logs_bloom": "Bloom" + }, + "Id": "AuthorityId", + "ChainId": "u8", + "ResourceId": "Vec", + "ExchangeId": "u64", + "CurrencyOf": "Balance", + "NftId": "U256", + "Erc721Token": { + "id": "NftId", + "metadata": "Vec" + } +} \ No newline at end of file diff --git a/workers/social-tokens-distributor/package.json b/workers/social-tokens-distributor/package.json new file mode 100644 index 000000000..100df3d50 --- /dev/null +++ b/workers/social-tokens-distributor/package.json @@ -0,0 +1,10 @@ +{ + "name": "social-tokens-distributor", + "version": "0.1.0", + "main": "index.js", + "license": "MIT", + "dependencies": { + "@polkadot/api": "^4.7.2", + "@polkadot/types": "^4.7.2" + } +} diff --git a/workers/social-tokens-distributor/src/index.ts b/workers/social-tokens-distributor/src/index.ts new file mode 100644 index 000000000..aee4ca9bc --- /dev/null +++ b/workers/social-tokens-distributor/src/index.ts @@ -0,0 +1,106 @@ +// Required imports +const { ApiPromise, WsProvider } = require("@polkadot/api"); +const { ISubmittableResult, EventRecord } = require("@polkadot/types/types"); +const { EraRewardPoints } = require("@polkadot/types/interfaces/staking"); +const { Keyring, KeyringPair } = require("@polkadot/keyring"); +const { randomAsU8a } = require("@polkadot/util-crypto"); + +const WS_URL = process.env.WS_URL; +const PHRASE = process.env.PHRASE; + +async function main() { + // Initialise the provider to connect to the local node + const provider = new WsProvider(WS_URL); + + const types = require("../config/types.json"); + + // Create the API and wait until ready + const api = await ApiPromise.create({ provider, types }); + + const keyring = new Keyring({ type: "sr25519" }); + const account = keyring.addFromUri(PHRASE); + + // Retrieve the chain & node information information via rpc calls + const [chain, nodeName, nodeVersion] = await Promise.all([ + api.rpc.system.chain(), + api.rpc.system.name(), + api.rpc.system.version(), + ]); + + console.log(`You are connected to chain ${chain} using ${nodeName} v${nodeVersion}`); + + const [historyDepth, currentEra] = await Promise.all([ + api.query.staking.historyDepth(), + api.query.staking.currentEra(), + ]); + + console.log(`Got init data from storage, historyDepth: ${historyDepth}, currentEra: ${currentEra}`); + + let { nonce } = await api.query.system.account(account.address); + for (let era = Math.max(currentEra - historyDepth, 0); era < currentEra; era ++) { + const erasRewardPoints: typeof EraRewardPoints = await api.query.staking.erasRewardPoints(era); + for (const stash in JSON.parse(erasRewardPoints.individual)) { + console.log(`Start processing, era: ${era}, stash: ${stash}, nonce: ${nonce}}`); + await payout_stakers(api, account, era, stash, nonce); + nonce++; + } + } + + sleep(1000); + console.log("Done"); +} + +async function payout_stakers( + api: typeof ApiPromise, + account: typeof KeyringPair, + era: number, + stash: string, + nonce: number, +) { + await api.tx.socialTreasury + .payoutStakers(stash, era) + .signAndSend(account, { nonce }, ({ events = [], status, dispatchError}: typeof ISubmittableResult) => { + console.log("Transaction status:", status.type); + + if (dispatchError) { + if (dispatchError.isModule) { + // for module errors, we have the section indexed, lookup + const decoded = api.registry.findMetaError(dispatchError.asModule); + const { documentation, name, section } = decoded; + console.log(`${section}.${name}: ${documentation.join(" ")}`); + } else { + // Other, CannotLookup, BadOrigin, no extra info + console.log(dispatchError.toString()); + } + } + + if (status.isInBlock) { + console.log("Included at block hash", status.asInBlock.toHex()); + console.log("Events:"); + + events.forEach(({ event: { data, method, section }, phase }: typeof EventRecord) => { + console.log("\t", phase.toString(), `: ${section}.${method}`, data.toString()); + }); + } else if (status.isFinalized) { + console.log("Finalized block hash", status.asFinalized.toHex()); + } + }); +} + +function sleep(ms: number) { + return new Promise((resolve) => setTimeout(resolve, ms)); +} + +function check_config() { + if (WS_URL == null) { + console.log("Please set WS_URL"); + process.exit(1); + } + if (PHRASE == null) { + console.log("Please set PHRASE"); + process.exit(1); + } +} + +check_config(); +main().catch(console.error).finally(() => process.exit()); diff --git a/workers/social-tokens-distributor/tsconfig.json b/workers/social-tokens-distributor/tsconfig.json new file mode 100644 index 000000000..ca2128200 --- /dev/null +++ b/workers/social-tokens-distributor/tsconfig.json @@ -0,0 +1,12 @@ +{ + "compilerOptions": { + "module": "commonjs", + "outDir": "dist", + "sourceMap": true, + "strict": true, + "target": "es2017" + }, + "include": [ + "src" + ] +} diff --git a/workers/social-tokens-distributor/yarn.lock b/workers/social-tokens-distributor/yarn.lock new file mode 100644 index 000000000..83f333274 --- /dev/null +++ b/workers/social-tokens-distributor/yarn.lock @@ -0,0 +1,637 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@babel/runtime@^7.13.17", "@babel/runtime@^7.13.9": + version "7.14.0" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.14.0.tgz#46794bc20b612c5f75e62dd071e24dfd95f1cbe6" + integrity sha512-JELkvo/DlpNdJ7dlyw/eY7E0suy5i5GQH+Vlxaq1nsNJ+H7f4Vtv3jMeCEgRhZZQFXTjldYfQgv2qmM6M1v5wA== + dependencies: + regenerator-runtime "^0.13.4" + +"@polkadot/api-derive@4.7.2": + version "4.7.2" + resolved "https://registry.yarnpkg.com/@polkadot/api-derive/-/api-derive-4.7.2.tgz#94ca16f2e61d1739489da6030cbe5137beee336a" + integrity sha512-TRctRtGFvsso5R/dGwna2QiaQy14NFhrthu/sLh3oYIMNwQ6BeGHhbfjAi0pidc+ID2ia6LDLRw7vl/LVSuHIA== + dependencies: + "@babel/runtime" "^7.13.17" + "@polkadot/api" "4.7.2" + "@polkadot/rpc-core" "4.7.2" + "@polkadot/types" "4.7.2" + "@polkadot/util" "^6.3.1" + "@polkadot/util-crypto" "^6.3.1" + "@polkadot/x-rxjs" "^6.3.1" + bn.js "^4.11.9" + +"@polkadot/api@4.7.2", "@polkadot/api@^4.7.2": + version "4.7.2" + resolved "https://registry.yarnpkg.com/@polkadot/api/-/api-4.7.2.tgz#0e98117fc631f2988ca364881111c05a00e8b701" + integrity sha512-PkWrgx+gICWt5uYjYoP68a8jyCRBkQXn9ecr0ReVr9jiiwvBYZyw3CLXTVRwJ89PpJLtDVz9QGCa4dM6j4a/LA== + dependencies: + "@babel/runtime" "^7.13.17" + "@polkadot/api-derive" "4.7.2" + "@polkadot/keyring" "^6.3.1" + "@polkadot/metadata" "4.7.2" + "@polkadot/rpc-core" "4.7.2" + "@polkadot/rpc-provider" "4.7.2" + "@polkadot/types" "4.7.2" + "@polkadot/types-known" "4.7.2" + "@polkadot/util" "^6.3.1" + "@polkadot/util-crypto" "^6.3.1" + "@polkadot/x-rxjs" "^6.3.1" + bn.js "^4.11.9" + eventemitter3 "^4.0.7" + +"@polkadot/keyring@^6.3.1": + version "6.3.1" + resolved "https://registry.yarnpkg.com/@polkadot/keyring/-/keyring-6.3.1.tgz#434847cc4fb134116691c07e05750e8388cbb2b7" + integrity sha512-uVWhdd4TVtLc4R2OtiKHJE5jgJZnuEognbgjl5RT2uKrCJYTsYnq0IeRTvMmtdPJAJvGeD3JTsX2ekgt3tJpuw== + dependencies: + "@babel/runtime" "^7.13.17" + "@polkadot/util" "6.3.1" + "@polkadot/util-crypto" "6.3.1" + +"@polkadot/metadata@4.7.2": + version "4.7.2" + resolved "https://registry.yarnpkg.com/@polkadot/metadata/-/metadata-4.7.2.tgz#91076a1c1158494574a1965ec1fe124fb4d1b848" + integrity sha512-+YWeD828cpIpD31epoSZfK5kmtJsBcgTTyYsQ4bBO4NBJceLTipmHgyLXs7fXjU4cC6uvSuBnAV0KGJW7L9nDQ== + dependencies: + "@babel/runtime" "^7.13.17" + "@polkadot/types" "4.7.2" + "@polkadot/types-known" "4.7.2" + "@polkadot/util" "^6.3.1" + "@polkadot/util-crypto" "^6.3.1" + bn.js "^4.11.9" + +"@polkadot/networks@6.3.1", "@polkadot/networks@^6.3.1": + version "6.3.1" + resolved "https://registry.yarnpkg.com/@polkadot/networks/-/networks-6.3.1.tgz#c5063681ea73f8b579f418d57d0eba2d4bb72292" + integrity sha512-oANup0CLGt75CPbE3gz2HUWUlqQKucImdb1TtStLXMUH+Aj8ZOnQFA2lwixzaRdx+ymPfmEL7GkF36i96OqQVw== + dependencies: + "@babel/runtime" "^7.13.17" + +"@polkadot/rpc-core@4.7.2": + version "4.7.2" + resolved "https://registry.yarnpkg.com/@polkadot/rpc-core/-/rpc-core-4.7.2.tgz#d79c42bb9fafc84a5c3b90959a86fe97b4a21fb5" + integrity sha512-LxpI8TVdjL99nfnLQog1tL0STdiYIUSLzdN+2PKvaO0YoBPAau945PVfz6GeN7wqQZKxR6N/1SKhAVfYcP7ctA== + dependencies: + "@babel/runtime" "^7.13.17" + "@polkadot/metadata" "4.7.2" + "@polkadot/rpc-provider" "4.7.2" + "@polkadot/types" "4.7.2" + "@polkadot/util" "^6.3.1" + "@polkadot/x-rxjs" "^6.3.1" + +"@polkadot/rpc-provider@4.7.2": + version "4.7.2" + resolved "https://registry.yarnpkg.com/@polkadot/rpc-provider/-/rpc-provider-4.7.2.tgz#71340ec6a109a2652502aee8d24e06f0322663b8" + integrity sha512-nvKScoPTzi7PFA5XnVI1lbebLjdwF6OcvWC0QvaEUrbwoG3NPFtoAGF6r2HloX0Q/Qo6FEHowrX0nY4gTM+QCw== + dependencies: + "@babel/runtime" "^7.13.17" + "@polkadot/types" "4.7.2" + "@polkadot/util" "^6.3.1" + "@polkadot/util-crypto" "^6.3.1" + "@polkadot/x-fetch" "^6.3.1" + "@polkadot/x-global" "^6.3.1" + "@polkadot/x-ws" "^6.3.1" + bn.js "^4.11.9" + eventemitter3 "^4.0.7" + +"@polkadot/types-known@4.7.2": + version "4.7.2" + resolved "https://registry.yarnpkg.com/@polkadot/types-known/-/types-known-4.7.2.tgz#d6b55c75a9461a09490167a679b6ed783eab6350" + integrity sha512-vlIMBtBdVYHyjWqonQ39PCdZJ9WeTsA5h5zr2mEpkCSoopby5pZ6eOR8CPqjc1uYbdDHT72Dbtx8Wr9L7z8HXg== + dependencies: + "@babel/runtime" "^7.13.17" + "@polkadot/networks" "^6.3.1" + "@polkadot/types" "4.7.2" + "@polkadot/util" "^6.3.1" + bn.js "^4.11.9" + +"@polkadot/types@4.7.2", "@polkadot/types@^4.7.2": + version "4.7.2" + resolved "https://registry.yarnpkg.com/@polkadot/types/-/types-4.7.2.tgz#6b3e8c16999951e040459d5e338e259543bfec16" + integrity sha512-8qj/f6YAv5XCDLej60uWlX+cjuz2qt6AJKemi+lozA4vYZ9XTXIODYLv/XfjimbVABzeLdIAwWX1OQO9+F0Gng== + dependencies: + "@babel/runtime" "^7.13.17" + "@polkadot/metadata" "4.7.2" + "@polkadot/util" "^6.3.1" + "@polkadot/util-crypto" "^6.3.1" + "@polkadot/x-rxjs" "^6.3.1" + "@types/bn.js" "^4.11.6" + bn.js "^4.11.9" + +"@polkadot/util-crypto@6.3.1", "@polkadot/util-crypto@^6.3.1": + version "6.3.1" + resolved "https://registry.yarnpkg.com/@polkadot/util-crypto/-/util-crypto-6.3.1.tgz#5328da77bdee5064bc41f9dec0a76cc634690b88" + integrity sha512-fwH4t6EN2XACwJB2Z5xUyNo4mQ1RXJj0MgVaaLua8PbG0qq9tt4eaEbdVzrm7A6igIfsTntDoZISTfVjBcRtkQ== + dependencies: + "@babel/runtime" "^7.13.17" + "@polkadot/networks" "6.3.1" + "@polkadot/util" "6.3.1" + "@polkadot/wasm-crypto" "^4.0.2" + "@polkadot/x-randomvalues" "6.3.1" + base-x "^3.0.8" + base64-js "^1.5.1" + blakejs "^1.1.0" + bn.js "^4.11.9" + create-hash "^1.2.0" + elliptic "^6.5.4" + hash.js "^1.1.7" + js-sha3 "^0.8.0" + scryptsy "^2.1.0" + tweetnacl "^1.0.3" + xxhashjs "^0.2.2" + +"@polkadot/util@6.3.1", "@polkadot/util@^6.3.1": + version "6.3.1" + resolved "https://registry.yarnpkg.com/@polkadot/util/-/util-6.3.1.tgz#410ee362ddb37f9c67af8f5897d977a7fd950ebf" + integrity sha512-M9pGaXSB67DZPckdNQU29wq5W7BUOh6qeu5LonzxpUek+riJfbiF9JOgZQ2Q/aEFYbd1hqLbOMsLRZLhSmlbYw== + dependencies: + "@babel/runtime" "^7.13.17" + "@polkadot/x-textdecoder" "6.3.1" + "@polkadot/x-textencoder" "6.3.1" + "@types/bn.js" "^4.11.6" + bn.js "^4.11.9" + camelcase "^5.3.1" + ip-regex "^4.3.0" + +"@polkadot/wasm-crypto-asmjs@^4.0.2": + version "4.0.2" + resolved "https://registry.yarnpkg.com/@polkadot/wasm-crypto-asmjs/-/wasm-crypto-asmjs-4.0.2.tgz#f42c353a64e1243841daf90e4bd54eff01a4e3cf" + integrity sha512-hlebqtGvfjg2ZNm4scwBGVHwOwfUhy2yw5RBHmPwkccUif3sIy4SAzstpcVBIVMdAEvo746bPWEInA8zJRcgJA== + dependencies: + "@babel/runtime" "^7.13.9" + +"@polkadot/wasm-crypto-wasm@^4.0.2": + version "4.0.2" + resolved "https://registry.yarnpkg.com/@polkadot/wasm-crypto-wasm/-/wasm-crypto-wasm-4.0.2.tgz#89f9e0a1e4d076784d4a42bea37fc8b06bdd8bb6" + integrity sha512-de/AfNPZ0uDKFWzOZ1rJCtaUbakGN29ks6IRYu6HZTRg7+RtqvE1rIkxabBvYgQVHIesmNwvEA9DlIkS6hYRFQ== + dependencies: + "@babel/runtime" "^7.13.9" + +"@polkadot/wasm-crypto@^4.0.2": + version "4.0.2" + resolved "https://registry.yarnpkg.com/@polkadot/wasm-crypto/-/wasm-crypto-4.0.2.tgz#9649057adee8383cc86433d107ba526b718c5a3b" + integrity sha512-2h9FuQFkBc+B3TwSapt6LtyPvgtd0Hq9QsHW8g8FrmKBFRiiFKYRpfJKHCk0aCZzuRf9h95bQl/X6IXAIWF2ng== + dependencies: + "@babel/runtime" "^7.13.9" + "@polkadot/wasm-crypto-asmjs" "^4.0.2" + "@polkadot/wasm-crypto-wasm" "^4.0.2" + +"@polkadot/x-fetch@^6.3.1": + version "6.3.1" + resolved "https://registry.yarnpkg.com/@polkadot/x-fetch/-/x-fetch-6.3.1.tgz#ac1737f57a2a03b6666aec6abe3c8a2e147c2696" + integrity sha512-goBtKZarq5sXV2G98inj2v1ivVNF9gif8sg6IqsGRbljca6K6pZWTVd0yGWe7OABnCkFQotk283nly9nkr9+1g== + dependencies: + "@babel/runtime" "^7.13.17" + "@polkadot/x-global" "6.3.1" + "@types/node-fetch" "^2.5.10" + node-fetch "^2.6.1" + +"@polkadot/x-global@6.3.1", "@polkadot/x-global@^6.3.1": + version "6.3.1" + resolved "https://registry.yarnpkg.com/@polkadot/x-global/-/x-global-6.3.1.tgz#cdb4883fa20e23411bdd5f50a5d5c92814a3106f" + integrity sha512-eFooGQdxJpiOsm3AKTSMInaecBKaQ/tqOUJNm/CpdJalCqTDMp/qzgj64Uflk9eUqGgk7jB7Q5FaQdyWsC0Mtg== + dependencies: + "@babel/runtime" "^7.13.17" + "@types/node-fetch" "^2.5.10" + node-fetch "^2.6.1" + +"@polkadot/x-randomvalues@6.3.1": + version "6.3.1" + resolved "https://registry.yarnpkg.com/@polkadot/x-randomvalues/-/x-randomvalues-6.3.1.tgz#e2b91223277d7d7978c39e9d280fbc6526217d46" + integrity sha512-SZ5MUYm1fd1fgGFexMWbbG8zZgCS7b9QNKaIcnv1Dwlfp2meDoDlgoedn+1pCJ6VEa1adswqLHX4WbYA4D9ynA== + dependencies: + "@babel/runtime" "^7.13.17" + "@polkadot/x-global" "6.3.1" + +"@polkadot/x-rxjs@^6.3.1": + version "6.3.1" + resolved "https://registry.yarnpkg.com/@polkadot/x-rxjs/-/x-rxjs-6.3.1.tgz#5627f9601df6db22a65512a3eab0af4a22a58830" + integrity sha512-Z9mbvpixr0fopQh049tFlR8r/RItOyYRL4P7YqwnfeROqxU4R8UTmmB8As9y/zy0O5Jlkjzy9MdyQgwzhGQOcQ== + dependencies: + "@babel/runtime" "^7.13.17" + rxjs "^6.6.7" + +"@polkadot/x-textdecoder@6.3.1": + version "6.3.1" + resolved "https://registry.yarnpkg.com/@polkadot/x-textdecoder/-/x-textdecoder-6.3.1.tgz#ab0eec87d5df2d119480fa7a3657d8d72f583af8" + integrity sha512-lLb11yaAmyx2STw7ZmdgPtV7LI26U/5h1K527cM7QnxgTQgYggtAt4f9aLHiWsmOCvnT0U0PWsWSUbAJrLHLBA== + dependencies: + "@babel/runtime" "^7.13.17" + "@polkadot/x-global" "6.3.1" + +"@polkadot/x-textencoder@6.3.1": + version "6.3.1" + resolved "https://registry.yarnpkg.com/@polkadot/x-textencoder/-/x-textencoder-6.3.1.tgz#2277770650f5637698d7d8cd7ac0cfd5ca0dace2" + integrity sha512-7V5OuT43JPTm7rrwdBEMzXAF5nLg+t6q24ntZHNcFUH1pdkP/+2f3vGM3e9BK5k4wkQLoepod5gyY6Qbw9bsYQ== + dependencies: + "@babel/runtime" "^7.13.17" + "@polkadot/x-global" "6.3.1" + +"@polkadot/x-ws@^6.3.1": + version "6.3.1" + resolved "https://registry.yarnpkg.com/@polkadot/x-ws/-/x-ws-6.3.1.tgz#1534f8d1cd03dbf497410725d14313e5554a2ffd" + integrity sha512-bDb9a+bxoaNOza0EeLp9M6FKYz9ogJcFQzRP+YR6ND7oQ0QcQG06XloRKTU0wtcZRKP8AzkYYN+FAc/6bnIqTw== + dependencies: + "@babel/runtime" "^7.13.17" + "@polkadot/x-global" "6.3.1" + "@types/websocket" "^1.0.2" + websocket "^1.0.34" + +"@types/bn.js@^4.11.6": + version "4.11.6" + resolved "https://registry.yarnpkg.com/@types/bn.js/-/bn.js-4.11.6.tgz#c306c70d9358aaea33cd4eda092a742b9505967c" + integrity sha512-pqr857jrp2kPuO9uRjZ3PwnJTjoQy+fcdxvBTvHm6dkmEL9q+hDD/2j/0ELOBPtPnS8LjCX0gI9nbl8lVkadpg== + dependencies: + "@types/node" "*" + +"@types/node-fetch@^2.5.10": + version "2.5.10" + resolved "https://registry.yarnpkg.com/@types/node-fetch/-/node-fetch-2.5.10.tgz#9b4d4a0425562f9fcea70b12cb3fcdd946ca8132" + integrity sha512-IpkX0AasN44hgEad0gEF/V6EgR5n69VEqPEgnmoM8GsIGro3PowbWs4tR6IhxUTyPLpOn+fiGG6nrQhcmoCuIQ== + dependencies: + "@types/node" "*" + form-data "^3.0.0" + +"@types/node@*": + version "15.0.1" + resolved "https://registry.yarnpkg.com/@types/node/-/node-15.0.1.tgz#ef34dea0881028d11398be5bf4e856743e3dc35a" + integrity sha512-TMkXt0Ck1y0KKsGr9gJtWGjttxlZnnvDtphxUOSd0bfaR6Q1jle+sPvrzNR1urqYTWMinoKvjKfXUGsumaO1PA== + +"@types/websocket@^1.0.2": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@types/websocket/-/websocket-1.0.2.tgz#d2855c6a312b7da73ed16ba6781815bf30c6187a" + integrity sha512-B5m9aq7cbbD/5/jThEr33nUY8WEfVi6A2YKCTOvw5Ldy7mtsOkqRvGjnzy6g7iMMDsgu7xREuCzqATLDLQVKcQ== + dependencies: + "@types/node" "*" + +asynckit@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" + integrity sha1-x57Zf380y48robyXkLzDZkdLS3k= + +base-x@^3.0.8: + version "3.0.8" + resolved "https://registry.yarnpkg.com/base-x/-/base-x-3.0.8.tgz#1e1106c2537f0162e8b52474a557ebb09000018d" + integrity sha512-Rl/1AWP4J/zRrk54hhlxH4drNxPJXYUaKffODVI53/dAsV4t9fBxyxYKAVPU1XBHxYwOWP9h9H0hM2MVw4YfJA== + dependencies: + safe-buffer "^5.0.1" + +base64-js@^1.5.1: + version "1.5.1" + resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" + integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== + +blakejs@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/blakejs/-/blakejs-1.1.0.tgz#69df92ef953aa88ca51a32df6ab1c54a155fc7a5" + integrity sha1-ad+S75U6qIylGjLfarHFShVfx6U= + +bn.js@^4.11.9: + version "4.12.0" + resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.12.0.tgz#775b3f278efbb9718eec7361f483fb36fbbfea88" + integrity sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA== + +brorand@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" + integrity sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8= + +bufferutil@^4.0.1: + version "4.0.3" + resolved "https://registry.yarnpkg.com/bufferutil/-/bufferutil-4.0.3.tgz#66724b756bed23cd7c28c4d306d7994f9943cc6b" + integrity sha512-yEYTwGndELGvfXsImMBLop58eaGW+YdONi1fNjTINSY98tmMmFijBG6WXgdkfuLNt4imzQNtIE+eBp1PVpMCSw== + dependencies: + node-gyp-build "^4.2.0" + +camelcase@^5.3.1: + version "5.3.1" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" + integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== + +cipher-base@^1.0.1: + version "1.0.4" + resolved "https://registry.yarnpkg.com/cipher-base/-/cipher-base-1.0.4.tgz#8760e4ecc272f4c363532f926d874aae2c1397de" + integrity sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q== + dependencies: + inherits "^2.0.1" + safe-buffer "^5.0.1" + +combined-stream@^1.0.8: + version "1.0.8" + resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" + integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== + dependencies: + delayed-stream "~1.0.0" + +create-hash@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/create-hash/-/create-hash-1.2.0.tgz#889078af11a63756bcfb59bd221996be3a9ef196" + integrity sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg== + dependencies: + cipher-base "^1.0.1" + inherits "^2.0.1" + md5.js "^1.3.4" + ripemd160 "^2.0.1" + sha.js "^2.4.0" + +cuint@^0.2.2: + version "0.2.2" + resolved "https://registry.yarnpkg.com/cuint/-/cuint-0.2.2.tgz#408086d409550c2631155619e9fa7bcadc3b991b" + integrity sha1-QICG1AlVDCYxFVYZ6fp7ytw7mRs= + +d@1, d@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/d/-/d-1.0.1.tgz#8698095372d58dbee346ffd0c7093f99f8f9eb5a" + integrity sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA== + dependencies: + es5-ext "^0.10.50" + type "^1.0.1" + +debug@^2.2.0: + version "2.6.9" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" + integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== + dependencies: + ms "2.0.0" + +delayed-stream@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" + integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk= + +elliptic@^6.5.4: + version "6.5.4" + resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.4.tgz#da37cebd31e79a1367e941b592ed1fbebd58abbb" + integrity sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ== + dependencies: + bn.js "^4.11.9" + brorand "^1.1.0" + hash.js "^1.0.0" + hmac-drbg "^1.0.1" + inherits "^2.0.4" + minimalistic-assert "^1.0.1" + minimalistic-crypto-utils "^1.0.1" + +es5-ext@^0.10.35, es5-ext@^0.10.50: + version "0.10.53" + resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.53.tgz#93c5a3acfdbef275220ad72644ad02ee18368de1" + integrity sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q== + dependencies: + es6-iterator "~2.0.3" + es6-symbol "~3.1.3" + next-tick "~1.0.0" + +es6-iterator@~2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/es6-iterator/-/es6-iterator-2.0.3.tgz#a7de889141a05a94b0854403b2d0a0fbfa98f3b7" + integrity sha1-p96IkUGgWpSwhUQDstCg+/qY87c= + dependencies: + d "1" + es5-ext "^0.10.35" + es6-symbol "^3.1.1" + +es6-symbol@^3.1.1, es6-symbol@~3.1.3: + version "3.1.3" + resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.3.tgz#bad5d3c1bcdac28269f4cb331e431c78ac705d18" + integrity sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA== + dependencies: + d "^1.0.1" + ext "^1.1.2" + +eventemitter3@^4.0.7: + version "4.0.7" + resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.7.tgz#2de9b68f6528d5644ef5c59526a1b4a07306169f" + integrity sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw== + +ext@^1.1.2: + version "1.4.0" + resolved "https://registry.yarnpkg.com/ext/-/ext-1.4.0.tgz#89ae7a07158f79d35517882904324077e4379244" + integrity sha512-Key5NIsUxdqKg3vIsdw9dSuXpPCQ297y6wBjL30edxwPgt2E44WcWBZey/ZvUc6sERLTxKdyCu4gZFmUbk1Q7A== + dependencies: + type "^2.0.0" + +form-data@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-3.0.1.tgz#ebd53791b78356a99af9a300d4282c4d5eb9755f" + integrity sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.8" + mime-types "^2.1.12" + +hash-base@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/hash-base/-/hash-base-3.1.0.tgz#55c381d9e06e1d2997a883b4a3fddfe7f0d3af33" + integrity sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA== + dependencies: + inherits "^2.0.4" + readable-stream "^3.6.0" + safe-buffer "^5.2.0" + +hash.js@^1.0.0, hash.js@^1.0.3, hash.js@^1.1.7: + version "1.1.7" + resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.7.tgz#0babca538e8d4ee4a0f8988d68866537a003cf42" + integrity sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA== + dependencies: + inherits "^2.0.3" + minimalistic-assert "^1.0.1" + +hmac-drbg@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" + integrity sha1-0nRXAQJabHdabFRXk+1QL8DGSaE= + dependencies: + hash.js "^1.0.3" + minimalistic-assert "^1.0.0" + minimalistic-crypto-utils "^1.0.1" + +inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== + +ip-regex@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/ip-regex/-/ip-regex-4.3.0.tgz#687275ab0f57fa76978ff8f4dddc8a23d5990db5" + integrity sha512-B9ZWJxHHOHUhUjCPrMpLD4xEq35bUTClHM1S6CBU5ixQnkZmwipwgc96vAd7AAGM9TGHvJR+Uss+/Ak6UphK+Q== + +is-typedarray@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" + integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo= + +js-sha3@^0.8.0: + version "0.8.0" + resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.8.0.tgz#b9b7a5da73afad7dedd0f8c463954cbde6818840" + integrity sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q== + +md5.js@^1.3.4: + version "1.3.5" + resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.5.tgz#b5d07b8e3216e3e27cd728d72f70d1e6a342005f" + integrity sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg== + dependencies: + hash-base "^3.0.0" + inherits "^2.0.1" + safe-buffer "^5.1.2" + +mime-db@1.47.0: + version "1.47.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.47.0.tgz#8cb313e59965d3c05cfbf898915a267af46a335c" + integrity sha512-QBmA/G2y+IfeS4oktet3qRZ+P5kPhCKRXxXnQEudYqUaEioAU1/Lq2us3D/t1Jfo4hE9REQPrbB7K5sOczJVIw== + +mime-types@^2.1.12: + version "2.1.30" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.30.tgz#6e7be8b4c479825f85ed6326695db73f9305d62d" + integrity sha512-crmjA4bLtR8m9qLpHvgxSChT+XoSlZi8J4n/aIdn3z92e/U47Z0V/yl+Wh9W046GgFVAmoNR/fmdbZYcSSIUeg== + dependencies: + mime-db "1.47.0" + +minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" + integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A== + +minimalistic-crypto-utils@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" + integrity sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo= + +ms@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" + integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= + +next-tick@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/next-tick/-/next-tick-1.0.0.tgz#ca86d1fe8828169b0120208e3dc8424b9db8342c" + integrity sha1-yobR/ogoFpsBICCOPchCS524NCw= + +node-fetch@^2.6.1: + version "2.6.1" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.1.tgz#045bd323631f76ed2e2b55573394416b639a0052" + integrity sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw== + +node-gyp-build@^4.2.0: + version "4.2.3" + resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.2.3.tgz#ce6277f853835f718829efb47db20f3e4d9c4739" + integrity sha512-MN6ZpzmfNCRM+3t57PTJHgHyw/h4OWnZ6mR8P5j/uZtqQr46RRuDE/P+g3n0YR/AiYXeWixZZzaip77gdICfRg== + +readable-stream@^3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198" + integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA== + dependencies: + inherits "^2.0.3" + string_decoder "^1.1.1" + util-deprecate "^1.0.1" + +regenerator-runtime@^0.13.4: + version "0.13.7" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz#cac2dacc8a1ea675feaabaeb8ae833898ae46f55" + integrity sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew== + +ripemd160@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-2.0.2.tgz#a1c1a6f624751577ba5d07914cbc92850585890c" + integrity sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA== + dependencies: + hash-base "^3.0.0" + inherits "^2.0.1" + +rxjs@^6.6.7: + version "6.6.7" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.6.7.tgz#90ac018acabf491bf65044235d5863c4dab804c9" + integrity sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ== + dependencies: + tslib "^1.9.0" + +safe-buffer@^5.0.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0, safe-buffer@~5.2.0: + version "5.2.1" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" + integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== + +scryptsy@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/scryptsy/-/scryptsy-2.1.0.tgz#8d1e8d0c025b58fdd25b6fa9a0dc905ee8faa790" + integrity sha512-1CdSqHQowJBnMAFyPEBRfqag/YP9OF394FV+4YREIJX4ljD7OxvQRDayyoyyCk+senRjSkP6VnUNQmVQqB6g7w== + +sha.js@^2.4.0: + version "2.4.11" + resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.4.11.tgz#37a5cf0b81ecbc6943de109ba2960d1b26584ae7" + integrity sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ== + dependencies: + inherits "^2.0.1" + safe-buffer "^5.0.1" + +string_decoder@^1.1.1: + version "1.3.0" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" + integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== + dependencies: + safe-buffer "~5.2.0" + +tslib@^1.9.0: + version "1.14.1" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" + integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== + +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@^1.0.1: + version "1.2.0" + resolved "https://registry.yarnpkg.com/type/-/type-1.2.0.tgz#848dd7698dafa3e54a6c479e759c4bc3f18847a0" + integrity sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg== + +type@^2.0.0: + version "2.5.0" + resolved "https://registry.yarnpkg.com/type/-/type-2.5.0.tgz#0a2e78c2e77907b252abe5f298c1b01c63f0db3d" + integrity sha512-180WMDQaIMm3+7hGXWf12GtdniDEy7nYcyFMKJn/eZz/6tSLXrUN9V0wKSbMjej0I1WHWbpREDEKHtqPQa9NNw== + +typedarray-to-buffer@^3.1.5: + version "3.1.5" + resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080" + integrity sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q== + dependencies: + is-typedarray "^1.0.0" + +utf-8-validate@^5.0.2: + version "5.0.4" + resolved "https://registry.yarnpkg.com/utf-8-validate/-/utf-8-validate-5.0.4.tgz#72a1735983ddf7a05a43a9c6b67c5ce1c910f9b8" + integrity sha512-MEF05cPSq3AwJ2C7B7sHAA6i53vONoZbMGX8My5auEVm6W+dJ2Jd/TZPyGJ5CH42V2XtbI5FD28HeHeqlPzZ3Q== + dependencies: + node-gyp-build "^4.2.0" + +util-deprecate@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" + integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= + +websocket@^1.0.34: + version "1.0.34" + resolved "https://registry.yarnpkg.com/websocket/-/websocket-1.0.34.tgz#2bdc2602c08bf2c82253b730655c0ef7dcab3111" + integrity sha512-PRDso2sGwF6kM75QykIesBijKSVceR6jL2G8NGYyq2XrItNC2P5/qL5XeR056GhA+Ly7JMFvJb9I312mJfmqnQ== + dependencies: + bufferutil "^4.0.1" + debug "^2.2.0" + es5-ext "^0.10.50" + typedarray-to-buffer "^3.1.5" + utf-8-validate "^5.0.2" + yaeti "^0.0.6" + +xxhashjs@^0.2.2: + version "0.2.2" + resolved "https://registry.yarnpkg.com/xxhashjs/-/xxhashjs-0.2.2.tgz#8a6251567621a1c46a5ae204da0249c7f8caa9d8" + integrity sha512-AkTuIuVTET12tpsVIQo+ZU6f/qDmKuRUcjaqR+OIvm+aCBsZ95i7UVY5WJ9TMsSaZ0DA2WxoZ4acu0sPH+OKAw== + dependencies: + cuint "^0.2.2" + +yaeti@^0.0.6: + version "0.0.6" + resolved "https://registry.yarnpkg.com/yaeti/-/yaeti-0.0.6.tgz#f26f484d72684cf42bedfb76970aa1608fbf9577" + integrity sha1-8m9ITXJoTPQr7ft2lwqhYI+/lXc=