From 6ca93a5d37ccbaf0f6ff438522393c765b16b413 Mon Sep 17 00:00:00 2001 From: Muhammad Abdul Hakim Shibghatallah <70675129+abdulhakim2902@users.noreply.github.com> Date: Wed, 20 Jul 2022 14:05:52 +0700 Subject: [PATCH] feat: sendTip and claimTips with octopusAssets (#135) * fix: remove unused methods * feat: implement octopusAsset for sendTip and claimTip * feat: implement octopusAsset for sendTip and claimTip * fix: benchmarking tipping pallet * fix: sendTip and claimTip test with octopusAssets * chore: bump version 2.1.4 * fix: event when claiming reference --- Cargo.lock | 12 +- node/Cargo.toml | 2 +- pallets/server/Cargo.toml | 2 +- pallets/tipping/Cargo.toml | 4 +- pallets/tipping/benchmarking/Cargo.toml | 4 +- pallets/tipping/benchmarking/src/lib.rs | 128 +--- pallets/tipping/benchmarking/src/mock.rs | 54 +- pallets/tipping/src/crypto.rs | 27 - pallets/tipping/src/functions.rs | 209 +++++ pallets/tipping/src/functions/api_call.rs | 54 -- pallets/tipping/src/functions/helper.rs | 195 ----- pallets/tipping/src/functions/mod.rs | 4 - pallets/tipping/src/functions/tips_balance.rs | 112 --- .../tipping/src/functions/unsigned_call.rs | 50 -- pallets/tipping/src/impl_tipping.rs | 468 ++---------- pallets/tipping/src/interface.rs | 59 +- pallets/tipping/src/lib.rs | 295 +------- pallets/tipping/src/mock.rs | 85 ++- pallets/tipping/src/tests.rs | 716 +++++------------- .../src/{types/tips_balance.rs => types.rs} | 42 +- pallets/tipping/src/types/api_response.rs | 147 ---- pallets/tipping/src/types/mod.rs | 3 - pallets/tipping/src/types/payload.rs | 113 --- pallets/tipping/src/weights.rs | 60 +- runtime/Cargo.toml | 2 +- runtime/src/lib.rs | 6 +- 26 files changed, 661 insertions(+), 2192 deletions(-) delete mode 100644 pallets/tipping/src/crypto.rs create mode 100644 pallets/tipping/src/functions.rs delete mode 100644 pallets/tipping/src/functions/api_call.rs delete mode 100644 pallets/tipping/src/functions/helper.rs delete mode 100644 pallets/tipping/src/functions/mod.rs delete mode 100644 pallets/tipping/src/functions/tips_balance.rs delete mode 100644 pallets/tipping/src/functions/unsigned_call.rs rename pallets/tipping/src/{types/tips_balance.rs => types.rs} (74%) delete mode 100644 pallets/tipping/src/types/api_response.rs delete mode 100644 pallets/tipping/src/types/mod.rs delete mode 100644 pallets/tipping/src/types/payload.rs diff --git a/Cargo.lock b/Cargo.lock index a9e1125..b57345f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3595,7 +3595,7 @@ dependencies = [ [[package]] name = "myriad" -version = "2.1.3" +version = "2.1.4" dependencies = [ "beefy-gadget", "beefy-gadget-rpc", @@ -3656,7 +3656,7 @@ dependencies = [ [[package]] name = "myriad-runtime" -version = "2.1.3" +version = "2.1.4" dependencies = [ "beefy-primitives", "frame-benchmarking", @@ -4223,7 +4223,7 @@ dependencies = [ [[package]] name = "pallet-server" -version = "2.1.3" +version = "2.1.4" dependencies = [ "frame-benchmarking", "frame-support", @@ -4292,7 +4292,7 @@ dependencies = [ [[package]] name = "pallet-tipping" -version = "2.1.3" +version = "2.1.4" dependencies = [ "frame-benchmarking", "frame-support", @@ -4300,6 +4300,7 @@ dependencies = [ "hex", "hex-literal", "log", + "pallet-assets", "pallet-balances", "pallet-server", "parity-scale-codec", @@ -4314,12 +4315,13 @@ dependencies = [ [[package]] name = "pallet-tipping-benchmarking" -version = "2.1.3" +version = "2.1.4" dependencies = [ "frame-benchmarking", "frame-support", "frame-system", "hex-literal", + "pallet-assets", "pallet-balances", "pallet-server", "pallet-tipping", diff --git a/node/Cargo.toml b/node/Cargo.toml index 99fee47..0609979 100644 --- a/node/Cargo.toml +++ b/node/Cargo.toml @@ -1,6 +1,6 @@ [package] name = 'myriad' -version = '2.1.3' +version = '2.1.4' edition = '2021' license = 'AGPL-3.0' authors = ['Myriad Dev Team '] diff --git a/pallets/server/Cargo.toml b/pallets/server/Cargo.toml index 0562fe3..88c41bf 100644 --- a/pallets/server/Cargo.toml +++ b/pallets/server/Cargo.toml @@ -1,6 +1,6 @@ [package] name = 'pallet-server' -version = '2.1.3' +version = '2.1.4' edition = '2021' license = 'AGPL-3.0' authors = ['Myriad Dev Team '] diff --git a/pallets/tipping/Cargo.toml b/pallets/tipping/Cargo.toml index d8c7208..9356396 100644 --- a/pallets/tipping/Cargo.toml +++ b/pallets/tipping/Cargo.toml @@ -1,6 +1,6 @@ [package] name = 'pallet-tipping' -version = '2.1.3' +version = '2.1.4' edition = '2021' license = 'AGPL-3.0' authors = ['Myriad Dev Team '] @@ -32,6 +32,7 @@ frame-benchmarking = { git = 'https://github.com/paritytech/substrate', branch = # Substrate Pallet Dependencies pallet-balances = { git = 'https://github.com/paritytech/substrate', branch = 'polkadot-v0.9.13', default-features = false } +pallet-assets = { git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.13', default-features = false } # Local Dependencies pallet-server = { path = '../server', default-features = false } @@ -58,6 +59,7 @@ std = [ 'frame-benchmarking/std', 'pallet-balances/std', + 'pallet-assets/std', 'pallet-server/std', ] diff --git a/pallets/tipping/benchmarking/Cargo.toml b/pallets/tipping/benchmarking/Cargo.toml index 1057baf..0b25ff7 100644 --- a/pallets/tipping/benchmarking/Cargo.toml +++ b/pallets/tipping/benchmarking/Cargo.toml @@ -1,6 +1,6 @@ [package] name = 'pallet-tipping-benchmarking' -version = '2.1.3' +version = '2.1.4' edition = '2021' license = 'AGPL-3.0' authors = ['Myriad Dev Team '] @@ -26,6 +26,7 @@ frame-benchmarking = { git = 'https://github.com/paritytech/substrate', branch = # Substrate Pallet Dependencies pallet-balances = { git = 'https://github.com/paritytech/substrate', branch = 'polkadot-v0.9.13', default-features = false } +pallet-assets = { git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.13', default-features = false } # Substrate Local Dependencies pallet-server = { path = '../../server', default-features = false } @@ -56,6 +57,7 @@ std = [ 'frame-benchmarking/std', 'pallet-balances/std', + 'pallet-assets/std', 'pallet-server/std', 'pallet-tipping/std', diff --git a/pallets/tipping/benchmarking/src/lib.rs b/pallets/tipping/benchmarking/src/lib.rs index b962184..d68f50f 100644 --- a/pallets/tipping/benchmarking/src/lib.rs +++ b/pallets/tipping/benchmarking/src/lib.rs @@ -58,59 +58,6 @@ benchmarks! { let balance = 1000000000000000000000u128.saturated_into(); let _ = ::Currency::deposit_creating(&tipping_account_id, balance); - let admin: T::AccountId = AdminKey::::get(); - let admin_origin = ::Origin::from(RawOrigin::Signed(admin)); - let server_name = b"myriad".to_vec(); - let server_id = b"server".to_vec(); - let server_api_url = b"https://api.dev.myriad.social".to_vec(); - let server_web_url = b"https://app.dev.myriad.social".to_vec(); - let _server = Server::::register( - admin_origin, - caller.clone(), - server_id.clone(), - server_name, - server_api_url, - server_web_url - ); - - // Send Tipping - let account_1: T::AccountId = account("account_1", 0, SEED); - let account_1_origin = ::Origin::from(RawOrigin::Signed(account_1.clone())); - let tips_balance_info = TipsBalanceInfo::new( - &server_id, - b"people", - b"people_id", - b"native" - ); - - let tipping_amount = 10000000000000000000u128.saturated_into(); - let _ = ::Currency::deposit_creating(&account_1, balance); - let _ = Tipping::::send_tip(account_1_origin, tips_balance_info.clone(), tipping_amount); - - // Send Tipping - let account_2: T::AccountId = account("account_2", 0, SEED); - let account_2_origin = ::Origin::from(RawOrigin::Signed(account_2.clone())); - let main_tips_balance_info = TipsBalanceInfo::new( - &server_id, - b"user", - b"user_id", - b"native" - ); - - let _ = ::Currency::deposit_creating(&account_2, balance); - let _ = Tipping::::send_tip(account_2_origin, main_tips_balance_info, tipping_amount); - - let trx_fee = 1000000000000000u128.saturated_into(); - let account_3: T::AccountId = account("account_3", 0, SEED); - }: _(RawOrigin::Signed(caller), tips_balance_info, b"user".to_vec(), b"user_id".to_vec(), Some(account_3), trx_fee) - - batch_claim_reference { - let caller: T::AccountId = whitelisted_caller(); - let tipping_account_id = Tipping::::tipping_account_id(); - - let balance = 1000000000000000000000u128.saturated_into(); - let _ = ::Currency::deposit_creating(&tipping_account_id, balance); - let admin: T::AccountId = AdminKey::::get(); let admin_origin = ::Origin::from(RawOrigin::Signed(admin)); let server_name = b"myriad".to_vec(); @@ -187,70 +134,6 @@ benchmarks! { server_web_url ); - // Send Tipping - let account_1: T::AccountId = account("account", 0, SEED); - let account_1_origin = ::Origin::from(RawOrigin::Signed(account_1.clone())); - let tips_balance_info = TipsBalanceInfo::new(&server_id, - b"people", - b"people_id", - b"native" - ); - - let tipping_amount = 10000000000000000000u128.saturated_into(); - let _ = ::Currency::deposit_creating(&account_1, balance); - let _ = Tipping::::send_tip(account_1_origin, tips_balance_info.clone(), tipping_amount); - - // Claim Reference - let account_2: T::AccountId = account("account_2", 0, SEED); - let account_2_origin = ::Origin::from(RawOrigin::Signed(account_2.clone())); - let tips_balance_info_user = TipsBalanceInfo::new( - &server_id, - b"user", - b"user_id", - b"native" - ); - - let _ = ::Currency::deposit_creating(&account_2, balance); - let _ = Tipping::::send_tip(account_2_origin, tips_balance_info_user.clone(), tipping_amount); - - let tx_fee = 10000000000000u128.saturated_into(); - let _ = Tipping::::claim_reference( - server_origin, - tips_balance_info, - b"user".to_vec(), - b"user_id".to_vec(), - Some(caller.clone()), - tx_fee, - ); - }: _(RawOrigin::Signed(caller), tips_balance_info_user) - - batch_claim_tip { - let caller: T::AccountId = whitelisted_caller(); - let tipping_account_id = Tipping::::tipping_account_id(); - - let balance = 1000000000000000000000u128.saturated_into(); - let _ = ::Currency::deposit_creating(&caller, balance); - let _ = ::Currency::deposit_creating(&tipping_account_id, balance); - - // Register Server - // Server admin => server_account - let admin: T::AccountId = AdminKey::::get(); - let server_account: T::AccountId = account("server_account", 0, SEED); - let admin_origin = ::Origin::from(RawOrigin::Signed(admin)); - let server_origin = ::Origin::from(RawOrigin::Signed(server_account.clone())); - let server_id = b"server".to_vec(); - let server_api_url = b"https://api.dev.myriad.social".to_vec(); - let server_web_url = b"https://app.dev.myriad.social".to_vec(); - - let _ = Server::::register( - admin_origin, - server_account, - server_id.clone(), - b"myriad".to_vec(), - server_api_url, - server_web_url - ); - // Send Tipping let account_1: T::AccountId = account("account", 0, SEED); let account_1_origin = ::Origin::from(RawOrigin::Signed(account_1.clone())); @@ -263,7 +146,7 @@ benchmarks! { let tipping_amount = 10000000000000000000u128.saturated_into(); let _ = ::Currency::deposit_creating(&account_1, balance); - let _ = Tipping::::send_tip(account_1_origin, tips_balance_info.clone(), tipping_amount); + let _ = Tipping::::send_tip(account_1_origin, tips_balance_info, tipping_amount); // Claim Reference let account_2: T::AccountId = account("account", 2, SEED); @@ -280,10 +163,11 @@ benchmarks! { let tx_fee = 10000000000000u128.saturated_into(); let _ = Tipping::::claim_reference( server_origin, - tips_balance_info, - b"user".to_vec(), - b"user_id".to_vec(), - Some(caller.clone()), + b"server".to_vec(), + References::new(b"people", &[b"people_id".to_vec()]), + References::new(b"user", &[b"user_id".to_vec()]), + vec![b"native".to_vec()], + caller.clone(), tx_fee, ); }: _(RawOrigin::Signed(caller), server_id, b"user".to_vec(), b"user_id".to_vec(), vec![b"native".to_vec()]) diff --git a/pallets/tipping/benchmarking/src/mock.rs b/pallets/tipping/benchmarking/src/mock.rs index 0eb9b81..fd4c086 100644 --- a/pallets/tipping/benchmarking/src/mock.rs +++ b/pallets/tipping/benchmarking/src/mock.rs @@ -5,8 +5,8 @@ use frame_system as system; use pallet_balances::AccountData; use sp_core::{sr25519::Signature, H256}; use sp_runtime::{ - testing::{Header, TestXt}, - traits::{BlakeTwo256, Extrinsic as ExtrinsicT, IdentifyAccount, IdentityLookup, Verify}, + testing::Header, + traits::{BlakeTwo256, IdentifyAccount, IdentityLookup, Verify}, }; type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; @@ -22,6 +22,7 @@ construct_runtime!( Balances: pallet_balances::{Pallet, Call, Storage, Config, Event}, Tipping: pallet_tipping::{Pallet, Call, Storage, Event}, Server: pallet_server::{Pallet, Call, Storage, Event}, + Assets: pallet_assets::{Pallet, Call, Storage, Event}, } ); @@ -79,11 +80,11 @@ impl pallet_balances::Config for Test { } impl pallet_tipping::Config for Test { - type AuthorityId = pallet_tipping::crypto::TestAuthId; type Call = Call; type Event = Event; type Currency = Balances; type Server = Server; + type Assets = Assets; type WeightInfo = (); } @@ -92,32 +93,31 @@ impl pallet_server::Config for Test { type WeightInfo = (); } -type Extrinsic = TestXt; -type AccountId = <::Signer as IdentifyAccount>::AccountId; +pub type OctopusAssetId = u32; +pub type OctopusAssetBalance = u128; -impl frame_system::offchain::SigningTypes for Test { - type Public = ::Signer; - type Signature = Signature; +parameter_types! { + pub const ApprovalDeposit: Balance = 1; + pub const AssetDeposit: Balance = 1; + pub const MetadataDepositBase: Balance = 1; + pub const MetadataDepositPerByte: Balance = 1; + pub const StringLimit: u32 = 50; } -impl frame_system::offchain::SendTransactionTypes for Test -where - Call: From, -{ - type OverarchingCall = Call; - type Extrinsic = Extrinsic; -} +type AccountId = <::Signer as IdentifyAccount>::AccountId; -impl system::offchain::CreateSignedTransaction for Test -where - Call: From, -{ - fn create_transaction>( - call: Call, - _public: ::Signer, - _account: AccountId, - nonce: u64, - ) -> Option<(Call, ::SignaturePayload)> { - Some((call, (nonce, ()))) - } +impl pallet_assets::Config for Test { + type Event = Event; + type Balance = OctopusAssetBalance; + type AssetId = OctopusAssetId; + type Currency = Balances; + type ForceOrigin = frame_system::EnsureRoot; + type AssetDeposit = AssetDeposit; + type MetadataDepositBase = MetadataDepositBase; + type MetadataDepositPerByte = MetadataDepositPerByte; + type ApprovalDeposit = ApprovalDeposit; + type StringLimit = StringLimit; + type Freezer = (); + type Extra = (); + type WeightInfo = (); } diff --git a/pallets/tipping/src/crypto.rs b/pallets/tipping/src/crypto.rs deleted file mode 100644 index 3f72719..0000000 --- a/pallets/tipping/src/crypto.rs +++ /dev/null @@ -1,27 +0,0 @@ -use frame_support::sp_runtime::{ - app_crypto::{app_crypto, sr25519}, - traits::Verify, - MultiSignature, MultiSigner, -}; -use sp_core::{crypto::KeyTypeId, sr25519::Signature as Sr25519Signature}; - -pub const KEY_TYPE: KeyTypeId = KeyTypeId(*b"btc!"); - -app_crypto!(sr25519, KEY_TYPE); - -pub struct TestAuthId; - -impl frame_system::offchain::AppCrypto for TestAuthId { - type RuntimeAppPublic = Public; - type GenericSignature = sp_core::sr25519::Signature; - type GenericPublic = sp_core::sr25519::Public; -} - -// implemented for mock runtime in test -impl frame_system::offchain::AppCrypto<::Signer, Sr25519Signature> - for TestAuthId -{ - type RuntimeAppPublic = Public; - type GenericSignature = sp_core::sr25519::Signature; - type GenericPublic = sp_core::sr25519::Public; -} diff --git a/pallets/tipping/src/functions.rs b/pallets/tipping/src/functions.rs new file mode 100644 index 0000000..2d4c7ce --- /dev/null +++ b/pallets/tipping/src/functions.rs @@ -0,0 +1,209 @@ +use crate::*; + +use frame_support::{ + sp_runtime::traits::{AccountIdConversion, SaturatedConversion, Saturating, Zero}, + traits::{fungibles, Currency, ExistenceRequirement, WithdrawReasons}, + PalletId, +}; +use sp_std::vec::Vec; + +const PALLET_ID: PalletId = PalletId(*b"Tipping!"); + +impl Pallet { + /// The account ID that holds tipping's funds + pub fn tipping_account_id() -> T::AccountId { + PALLET_ID.into_account() + } + + pub fn can_update_balance(tips_balance_key: &TipsBalanceKey) -> bool { + TipsBalanceByReference::::contains_key(tips_balance_key) + } + + pub fn can_pay_fee( + tips_balance_key: &TipsBalanceKey, + tx_fee: &BalanceOf, + ) -> Result<(), Error> { + if tx_fee == &Zero::zero() { + return Err(Error::::FailedToVerify) + } + + let tips_balance = + Self::tips_balance_by_reference(tips_balance_key).ok_or(Error::::FailedToVerify)?; + + let amount = tips_balance.get_amount(); + + if amount == &Zero::zero() { + return Err(Error::::FailedToVerify) + } + + if amount < tx_fee { + return Err(Error::::FailedToVerify) + } + + Ok(()) + } + + pub fn can_claim_tip( + tips_balance_key: &TipsBalanceKey, + receiver: &AccountIdOf, + ) -> Option> { + if let Some(tips_balance) = Self::tips_balance_by_reference(tips_balance_key) { + if tips_balance.get_amount() == &Zero::zero() { + return None + } + + if tips_balance.get_account_id().is_none() { + return None + } + + if tips_balance.get_account_id().as_ref().unwrap() != receiver { + return None + } + + return Some(tips_balance) + } + + None + } + + pub fn do_server_exist( + server_id: &[u8], + sender: Option<&T::AccountId>, + ) -> Result<(), Error> { + let server = T::Server::get_by_id(server_id).ok_or(Error::::ServerNotRegister)?; + + if sender.is_none() { + return Ok(()) + } + + if sender.unwrap() != server.get_owner() { + return Err(Error::::Unauthorized) + } + + Ok(()) + } + + pub fn do_store_tips_balance( + tips_balance: &TipsBalanceOf, + set_empty: bool, + tx_fee: Option>, + ) -> BalanceOf { + let tips_balance_key = tips_balance.key(); + let amount = *tips_balance.get_amount(); + let account_id = tips_balance.get_account_id(); + let ft_identifier = tips_balance.get_ft_identifier(); + + // Total tip that has been send and claim + let mut total_tip: BalanceOf = amount; + + if Self::can_update_balance(&tips_balance_key) { + TipsBalanceByReference::::mutate( + tips_balance_key, + |tips_balance| match tips_balance { + Some(tips_balance) => { + if set_empty { + tips_balance.set_amount(Zero::zero()); + } else if tx_fee.is_some() && ft_identifier == b"native" { + let current_balance = *tips_balance.get_amount(); + let final_balance = current_balance + .saturating_sub(tx_fee.unwrap()) + .saturating_add(amount); + tips_balance.set_amount(final_balance); + total_tip = final_balance; + } else { + tips_balance.add_amount(amount); + } + + if account_id.is_some() { + tips_balance.set_account_id(account_id.as_ref().unwrap()); + } + }, + None => (), + }, + ); + } else { + TipsBalanceByReference::::insert(tips_balance.key(), tips_balance); + } + + total_tip + } + + pub fn do_transfer( + ft_identifier: &[u8], + sender: &AccountIdOf, + receiver: &AccountIdOf, + amount: BalanceOf, + ) -> Result<(), Error> { + if ft_identifier == b"native" { + let imb = CurrencyOf::::withdraw( + sender, + amount, + WithdrawReasons::TRANSFER, + ExistenceRequirement::KeepAlive, + ) + .map_err(|_| Error::::BadSignature)?; + + CurrencyOf::::resolve_creating(receiver, imb); + } else { + let asset_id = Self::asset_id(ft_identifier)?; + let _ = >::teleport( + asset_id, + sender, + receiver, + amount.saturated_into(), + ) + .map_err(|_| Error::::BadSignature)?; + } + + Ok(()) + } + + pub fn do_store_tips_balances( + server_id: &[u8], + references: &References, + main_references: &References, + ft_identifiers: &[FtIdentifier], + account_id: &AccountIdOf, + tx_fee: &BalanceOf, + ) -> Vec> { + let mut main_tips_balances = Vec::>::new(); + let ref_type = main_references.get_reference_type(); + let ref_id = &main_references.get_reference_ids()[0]; + + for ft_identifier in ft_identifiers.iter() { + let mut tip: BalanceOf = Zero::zero(); + let reference_type = references.get_reference_type(); + let reference_ids = references.get_reference_ids(); + + for reference_id in reference_ids { + let tips_balance_key = (server_id, reference_type, reference_id, ft_identifier); + if let Some(tips_balance) = Self::tips_balance_by_reference(&tips_balance_key) { + let amount = *tips_balance.get_amount(); + if amount > Zero::zero() { + tip = tip.saturating_add(amount); + Self::do_store_tips_balance(&tips_balance, true, None); + } + } + } + + let main_info = TipsBalanceInfo::new(server_id, ref_type, ref_id, ft_identifier); + let mut main_balance = TipsBalance::new(&main_info, &tip); + + main_balance.set_account_id(account_id); + + let total_tip = Self::do_store_tips_balance(&main_balance, false, Some(*tx_fee)); + + main_balance.set_amount(total_tip); + main_tips_balances.push(main_balance); + } + + main_tips_balances + } + + pub fn asset_id(ft_identifier: &[u8]) -> Result> { + let str_num = + String::from_utf8(ft_identifier.to_vec()).map_err(|_| Error::::WrongFormat)?; + + str_num.parse::().map_err(|_| Error::::WrongFormat) + } +} diff --git a/pallets/tipping/src/functions/api_call.rs b/pallets/tipping/src/functions/api_call.rs deleted file mode 100644 index 5aad8d3..0000000 --- a/pallets/tipping/src/functions/api_call.rs +++ /dev/null @@ -1,54 +0,0 @@ -use crate::*; - -use frame_support::sp_runtime::offchain::http::{Method, Request, Response}; -use sp_std::{str, vec, vec::Vec}; - -impl Pallet { - pub fn myriad_api_request( - payload: &Payload>, - method: Method, - ) -> Result { - let api_url_str = str::from_utf8(payload.get_api_url()); - let access_token_str = str::from_utf8(payload.get_access_token()); - - let access_token = access_token_str.map_err(|_| "Failed to format acces token")?; - let api_url = api_url_str.map_err(|_| "Failed to format api url")?; - let body = payload.get_body(); - let request_body = vec![body.clone()]; - let init_request = Request::>>::new(api_url) - .method(method.clone()) - .add_header("Authorization", access_token) - .add_header("content-type", "application/json"); - - let request = match method { - Method::Delete => init_request, - _ => init_request.body(request_body), - }; - - let pending = request.send().map_err(|_| "Request timeout")?; - let response = pending.wait().map_err(|_| "Failed to response")?; - - if response.code != 200 { - let body_str = Self::parse_body_reponse(response)?; - - log::info!("{}", body_str); - - return Err("Status code error") - } - - if method == Method::Delete { - return Ok(String::new()) - } - - Self::parse_body_reponse(response) - } - - pub fn parse_body_reponse(response: Response) -> Result { - let body = response.body().collect::>(); - - match str::from_utf8(&body) { - Ok(result) => Ok(result.to_string()), - Err(_) => Err("Failed to parse body"), - } - } -} diff --git a/pallets/tipping/src/functions/helper.rs b/pallets/tipping/src/functions/helper.rs deleted file mode 100644 index 9ba2a3a..0000000 --- a/pallets/tipping/src/functions/helper.rs +++ /dev/null @@ -1,195 +0,0 @@ -use crate::*; - -use codec::Encode; -use frame_support::{ - sp_runtime::{ - offchain::storage::StorageValueRef, - traits::AccountIdConversion, - transaction_validity::{InvalidTransaction, TransactionValidity, ValidTransaction}, - }, - PalletId, -}; -use frame_system as system; -use sp_io::offchain_index; -use sp_std::{str, vec::Vec}; - -const PALLET_ID: PalletId = PalletId(*b"Tipping!"); -const ONCHAIN_TX_KEY: &[u8] = b"pallet_tipping::indexing"; -const UNSIGNED_TXS_PRIORITY: u64 = 100; - -impl Pallet { - /// The account ID that holds tipping's funds - pub fn tipping_account_id() -> T::AccountId { - PALLET_ID.into_account() - } - - pub fn verify_server( - sender: &Option, - server_id: &[u8], - verify_owner: bool, - ) -> Result<(), Error> { - let server = T::Server::get_by_id(server_id); - - if server.is_none() { - return Err(Error::::ServerNotRegister) - } - - if !verify_owner { - return Ok(()) - } - - if sender.is_none() { - return Err(Error::::Unauthorized) - } - - let sender = sender.clone().unwrap(); - let server = server.unwrap(); - let server_owner = server.get_owner(); - - if &sender != server_owner { - return Err(Error::::Unauthorized) - } - - Ok(()) - } - - pub fn derived_key(block_number: T::BlockNumber) -> Vec { - block_number.using_encoded(|encoded_bn| { - ONCHAIN_TX_KEY - .to_vec() - .iter() - .chain(b"/".iter()) - .chain(encoded_bn) - .copied() - .collect::>() - }) - } - - pub fn get_indexing_data(block_number: T::BlockNumber) -> Option>> { - let key = Self::derived_key(block_number); - let mut storage_ref = StorageValueRef::persistent(&key); - - match storage_ref.get::>>() { - Ok(data) => { - storage_ref.clear(); - data - }, - Err(_) => None, - } - } - - pub fn validate_transaction_parameters( - block_number: &T::BlockNumber, - provide: &[u8], - ) -> TransactionValidity { - let current_block = >::block_number(); - if ¤t_block < block_number { - return InvalidTransaction::Future.into() - } - - let valid_tx = |provide| { - ValidTransaction::with_tag_prefix("pallet_tipping") - .priority(UNSIGNED_TXS_PRIORITY) - .and_provides([&provide]) - .longevity(5) - .propagate(true) - .build() - }; - - valid_tx(provide.to_vec()) - } - - pub fn get_api_url(server_id: &[u8], endpoint: &str) -> Result, Error> { - let server = T::Server::get_by_id(server_id); - - if server.is_none() { - return Err(Error::::ServerNotRegister) - } - - let mut api_url = server.unwrap().get_api_url().to_vec(); - let mut endpoint = endpoint.as_bytes().to_vec(); - - api_url.append(&mut endpoint); - - Ok(api_url) - } - - pub fn store_deleted_payload( - server_id: &[u8], - access_token: &[u8], - data_type: &DataType, - ) -> Result<(), Error> { - let endpoint = match data_type { - DataType::UserSocialMedia(user_social_media_info) => { - Self::deposit_event(Event::::VerifyingSocialMedia(Status::Failed, None)); - - let mut endpoint = String::from("/user-social-medias/"); - let id = str::from_utf8(user_social_media_info.get_id()).unwrap_or("id"); - - endpoint.push_str(id); - - endpoint - }, - DataType::Wallet(wallet_info) => { - Self::deposit_event(Event::::ConnectingAccount(Status::Failed, None)); - - let mut endpoint = String::from("/wallets/"); - let id = str::from_utf8(wallet_info.get_id()).unwrap_or("id"); - - endpoint.push_str(id); - - endpoint - }, - }; - - match Self::get_api_url(server_id, &endpoint) { - Ok(api_url) => { - let payload = Payload::>::init(server_id, &api_url, access_token); - let key = Self::derived_key(>::block_number()); - let data = IndexingData::init(b"remove_data_unsigned", payload); - - offchain_index::set(&key, &data.encode()); - - Ok(()) - }, - Err(err) => Err(err), - } - } - - pub fn parse_user_social_media(data: &str) -> Option { - let data = str::replace(data, "createdAt", "created_at"); - let data = str::replace(&data, "updatedAt", "updated_at"); - let data = str::replace(&data, "peopleId", "people_id"); - let data = str::replace(&data, "userId", "user_id"); - - match serde_json::from_str::(&data) { - Ok(result) => Some(DataType::UserSocialMedia(result)), - Err(_) => None, - } - } - - pub fn parse_wallet(data: &str) -> Option { - let data = str::replace(data, "createdAt", "created_at"); - let data = str::replace(&data, "updatedAt", "updated_at"); - let data = str::replace(&data, "networkId", "network_id"); - let data = str::replace(&data, "userId", "user_id"); - - match serde_json::from_str::(&data) { - Ok(result) => Some(DataType::Wallet(result)), - Err(_) => None, - } - } - - pub fn is_integer(ft_identifier: &[u8]) -> bool { - if ft_identifier == "native".as_bytes() { - return true - }; - - let str_num = match String::from_utf8(ft_identifier.to_vec()) { - Ok(res) => res, - Err(err) => err.to_string(), - }; - - str_num.parse::().is_ok() - } -} diff --git a/pallets/tipping/src/functions/mod.rs b/pallets/tipping/src/functions/mod.rs deleted file mode 100644 index 6d58e09..0000000 --- a/pallets/tipping/src/functions/mod.rs +++ /dev/null @@ -1,4 +0,0 @@ -mod api_call; -mod helper; -mod tips_balance; -mod unsigned_call; diff --git a/pallets/tipping/src/functions/tips_balance.rs b/pallets/tipping/src/functions/tips_balance.rs deleted file mode 100644 index 83f6464..0000000 --- a/pallets/tipping/src/functions/tips_balance.rs +++ /dev/null @@ -1,112 +0,0 @@ -use crate::*; - -use frame_support::sp_runtime::traits::Zero; -use sp_std::vec::Vec; - -impl Pallet { - pub fn get_tips_balance(tips_balance_info: &TipsBalanceInfo) -> Option> { - let reference_type = tips_balance_info.get_reference_type(); - let reference_id = tips_balance_info.get_reference_id(); - let server_id = tips_balance_info.get_server_id(); - let ft_identifier = tips_balance_info.get_ft_identifier(); - - Self::tips_balance_by_reference((server_id, reference_type, reference_id, ft_identifier)) - } - - pub fn create_tips_balance( - tips_balance_info: &TipsBalanceInfo, - account_id: &Option>, - amount: &Option>, - ) -> TipsBalanceOf { - let server_id = tips_balance_info.get_server_id(); - let reference_type = tips_balance_info.get_reference_type(); - let reference_id = tips_balance_info.get_reference_id(); - let ft_identifier = tips_balance_info.get_ft_identifier(); - let amount = if amount.is_some() { amount.unwrap() } else { Zero::zero() }; - let tips_balance = TipsBalance::new(tips_balance_info, account_id, &amount); - - TipsBalanceByReference::::insert( - (server_id, reference_type, reference_id, ft_identifier), - tips_balance.clone(), - ); - - tips_balance - } - - pub fn update_tips_balance(tips_balance: &TipsBalanceOf) -> TipsBalanceOf { - let tips_balance_info = tips_balance.get_tips_balance_info(); - let server_id = tips_balance_info.get_server_id(); - let reference_type = tips_balance_info.get_reference_type(); - let reference_id = tips_balance_info.get_reference_id(); - let ft_identifier = tips_balance_info.get_ft_identifier(); - - TipsBalanceByReference::::insert( - (server_id, reference_type, reference_id, ft_identifier), - tips_balance.clone(), - ); - - tips_balance.clone() - } - - pub fn update_tips_balances( - server_id: &[u8], - references: &References, - main_references: &References, - ft_identifiers: &[FtIdentifier], - account_id: &AccountIdOf, - tx_fee: &BalanceOf, - tips_balance: &TipsBalanceOf, - ) -> Vec> { - let mut main_tips_balances = Vec::>::new(); - let ref_type = main_references.get_reference_type(); - let ref_id = &main_references.get_reference_ids()[0]; - for ft_identifier in ft_identifiers.iter() { - // Remove when other token is implemented - // Check existing currency - if ft_identifier != b"native" { - continue - } - - let mut tip: BalanceOf = Zero::zero(); - let reference_type = references.get_reference_type(); - let reference_ids = references.get_reference_ids(); - for reference_id in reference_ids { - let tips_balance_info = - TipsBalanceInfo::new(server_id, reference_type, reference_id, ft_identifier); - - if let Some(mut tips_balance) = Self::get_tips_balance(&tips_balance_info) { - if *tips_balance.get_amount() > Zero::zero() { - tip += *tips_balance.get_amount(); - tips_balance.set_amount(Zero::zero()); - Self::update_tips_balance(&tips_balance); - } - } - } - - let main_info = TipsBalanceInfo::new(server_id, ref_type, ref_id, ft_identifier); - let main_balance = if ft_identifier != b"native" { - match Self::get_tips_balance(&main_info) { - Some(mut res) => { - let amount = *res.get_amount(); - res.set_amount(tip + amount); - res.set_account_id(&Some(account_id.clone())); - res - }, - None => TipsBalance::new(&main_info, &Some(account_id.clone()), &tip), - } - } else { - let mut tips_balance = tips_balance.clone(); - let amount = *tips_balance.get_amount(); - - tips_balance.set_amount(tip + amount - *tx_fee); - tips_balance.set_account_id(&Some(account_id.clone())); - tips_balance.clone() - }; - - Self::update_tips_balance(&main_balance); - main_tips_balances.push(main_balance); - } - - main_tips_balances - } -} diff --git a/pallets/tipping/src/functions/unsigned_call.rs b/pallets/tipping/src/functions/unsigned_call.rs deleted file mode 100644 index b14c5c2..0000000 --- a/pallets/tipping/src/functions/unsigned_call.rs +++ /dev/null @@ -1,50 +0,0 @@ -use crate::*; - -use frame_support::sp_runtime::offchain::http::Method; -use frame_system::offchain::SubmitTransaction; - -impl Pallet { - pub fn verify_social_media_and_send_unsigned( - block_number: T::BlockNumber, - ) -> Result, &'static str> { - let mut log_info: Option<&str> = None; - - let data = Self::get_indexing_data(block_number).ok_or("Empty storage")?; - let payload = data.get_payload(); - let payload_type = payload.get_payload_type().clone(); - - let body_str = match &payload_type { - PayloadType::Create => Self::myriad_api_request(payload, Method::Post), - PayloadType::Connect => Self::myriad_api_request(payload, Method::Post), - PayloadType::Delete => Self::myriad_api_request(payload, Method::Delete), - }; - - let init = APIResult::init( - payload.get_server_id(), - payload.get_ft_identifier(), - payload.get_access_token(), - ); - - let account_id = payload.get_account_id().clone(); - let api_response = if let Err(err) = body_str { - log_info = Some(err); - init - } else { - let body_str = body_str.unwrap(); - let data_type = match &payload_type { - PayloadType::Create => Self::parse_user_social_media(&body_str), - PayloadType::Connect => Self::parse_wallet(&body_str), - PayloadType::Delete => None, - }; - - init.set_data_type(data_type).set_account_id(account_id) - }; - - let call = Call::claim_reference_unsigned { block_number, payload_type, api_response }; - - match SubmitTransaction::>::submit_unsigned_transaction(call.into()) { - Ok(_) => Ok(log_info), - Err(_) => Err("Failed in offchain_unsigned_tx"), - } - } -} diff --git a/pallets/tipping/src/impl_tipping.rs b/pallets/tipping/src/impl_tipping.rs index e4bdafc..38eba57 100644 --- a/pallets/tipping/src/impl_tipping.rs +++ b/pallets/tipping/src/impl_tipping.rs @@ -1,466 +1,122 @@ use super::*; -use codec::Encode; -use frame_support::{ - sp_runtime::traits::Zero, - traits::{Currency, ExistenceRequirement, WithdrawReasons}, -}; -use serde_json::json; -use sp_io::offchain_index; -use sp_std::{str, vec, vec::Vec}; +use sp_std::vec::Vec; impl TippingInterface for Pallet { type Error = Error; - type TipsBalance = TipsBalanceOf; - type TipsBalances = Vec>; type TipsBalanceInfo = TipsBalanceInfo; + type TipsBalanceKey = TipsBalanceKey; type Balance = BalanceOf; - type UserCredential = UserCredential; - type SocialMediaCredential = SocialMediaCredential; type ServerId = ServerId; type References = References; type ReferenceType = ReferenceType; type ReferenceId = ReferenceId; - type ReferenceIds = Vec; type FtIdentifier = FtIdentifier; - type AccessToken = AccessToken; - type DataId = Vec; - type DataType = DataType; type FtIdentifiers = Vec; - type FtIdentifierBalances = Vec<(BalanceOf, FtIdentifier)>; + type SendTipResult = (AccountIdOf, TipsBalanceTuppleOf); + type ClaimTipResult = (AccountIdOf, AccountBalancesTuppleOf); + type ClaimReferenceResult = Vec>; fn send_tip( sender: &T::AccountId, tips_balance_info: &Self::TipsBalanceInfo, amount: &Self::Balance, - ) -> Result { + ) -> Result { + let receiver = Self::tipping_account_id(); let server_id = tips_balance_info.get_server_id(); - let ft_identifier = tips_balance_info.get_ft_identifier(); let tip_amount = *amount; + let ft_identifier = tips_balance_info.get_ft_identifier(); + let tips_balance = TipsBalance::new(tips_balance_info, amount); - if T::Server::get_by_id(server_id).is_none() { - return Err(Error::::ServerNotRegister) - } - - if !Self::is_integer(ft_identifier) { - return Err(Error::::WrongFormat) - } - - if ft_identifier != "native".as_bytes() { - return Err(Error::::FtNotExists) - } - - if CurrencyOf::::free_balance(sender) < tip_amount { - return Err(Error::::InsufficientBalance) - } - - match CurrencyOf::::withdraw( - sender, - tip_amount, - WithdrawReasons::TRANSFER, - ExistenceRequirement::KeepAlive, - ) { - Ok(imb) => { - let receiver = Self::tipping_account_id(); - let tips_balance = match Self::get_tips_balance(tips_balance_info) { - Some(mut result) => { - let total_amount = *result.get_amount() + tip_amount; - - result.set_amount(total_amount); - Self::update_tips_balance(&result) - }, - None => Self::create_tips_balance(tips_balance_info, &None, &Some(tip_amount)), - }; - - CurrencyOf::::resolve_creating(&receiver, imb); + Self::do_server_exist(server_id, None)?; + Self::do_transfer(ft_identifier, sender, &receiver, tip_amount)?; + Self::do_store_tips_balance(&tips_balance, false, None); - Ok(tips_balance) - }, - _ => Err(Error::::BadSignature), - } + Ok((receiver, (tips_balance.key(), tip_amount))) } fn claim_tip( receiver: &T::AccountId, - tips_balance_info: &Self::TipsBalanceInfo, - ) -> Result<(Self::Balance, Self::FtIdentifier), Self::Error> { - let sender = Self::tipping_account_id(); - let tips_balance = Self::get_tips_balance(tips_balance_info); - - if tips_balance.is_none() { - return Err(Error::::NotExists) - } - - let mut tips_balance = tips_balance.unwrap(); - let ft_identifier = tips_balance.get_ft_identifier().clone(); - let account_id = tips_balance.get_account_id().as_ref(); - let amount = *tips_balance.get_amount(); - - if amount == Zero::zero() { - return Err(Error::::NothingToClaimed) - } - - if account_id.is_none() { - return Err(Error::::ReceiverNotExists) - } - - if account_id.unwrap() != receiver { - return Err(Error::::Unauthorized) - } - - if !Self::is_integer(&ft_identifier) { - return Err(Error::::WrongFormat) - } - - if ft_identifier != "native".as_bytes() { - return Err(Error::::FtNotExists) - } - - tips_balance.set_amount(Zero::zero()); - - match CurrencyOf::::withdraw( - &sender, - amount, - WithdrawReasons::TRANSFER, - ExistenceRequirement::KeepAlive, - ) { - Ok(imb) => { - CurrencyOf::::resolve_creating(receiver, imb); - - let _ = Self::update_tips_balance(&tips_balance); - - Ok((amount, ft_identifier)) - }, - _ => Err(Error::::BadSignature), - } - } - - fn batch_claim_tip( - receiver: &T::AccountId, - server_id: &Self::ServerId, - reference_type: &Self::ReferenceType, - reference_id: &Self::ReferenceId, + tips_balance_key: &Self::TipsBalanceKey, ft_identifiers: &Self::FtIdentifiers, - ) -> Result { - let tips_balances: Vec> = (0..ft_identifiers.len()) - .filter_map(|index| { - let ft_identifier = &ft_identifiers[index]; - - if ft_identifier != b"native" { - return None - } - - let tips_balance_info = - TipsBalanceInfo::new(server_id, reference_type, reference_id, ft_identifier); - let tips_balance = Self::get_tips_balance(&tips_balance_info); - - if let Some(tips_balance) = tips_balance { - if tips_balance.get_amount() == &Zero::zero() { - return None - } - - if tips_balance.get_account_id().is_none() { - return None - } - - if tips_balance.get_account_id().as_ref().unwrap() != receiver { - return None - } - - return Some(tips_balance) - } - - None - }) - .collect(); - - if tips_balances.is_empty() { - return Err(Error::::NothingToClaimed) - } - + ) -> Result { let sender = Self::tipping_account_id(); - let mut success_claim = Vec::<(BalanceOf, FtIdentifier)>::new(); - for tips_balance in tips_balances.iter() { - let ft = tips_balance.get_ft_identifier(); - let tips_amount = tips_balance.get_amount(); - let receiver = tips_balance.get_account_id().as_ref().unwrap(); - let mut tips_balance = tips_balance.clone(); + let mut tips_balance_key = tips_balance_key.clone(); + let mut success_claim = Vec::new(); + let mut failed_claim = Vec::new(); + + for ft in ft_identifiers.iter() { + tips_balance_key.3 = ft.clone(); - tips_balance.set_amount(Zero::zero()); + let can_claim_tip = Self::can_claim_tip(&tips_balance_key, receiver); - if ft != b"native" { + if can_claim_tip.is_none() { continue } - if let Ok(imb) = CurrencyOf::::withdraw( - &sender, - *tips_amount, - WithdrawReasons::TRANSFER, - ExistenceRequirement::KeepAlive, - ) { - CurrencyOf::::resolve_creating(receiver, imb); + let tips_balance = can_claim_tip.unwrap(); + let amount = *tips_balance.get_amount(); - let _ = Self::update_tips_balance(&tips_balance); + match Self::do_transfer(ft, &sender, receiver, amount) { + Ok(_) => { + Self::do_store_tips_balance(&tips_balance, true, None); - success_claim.push((*tips_amount, ft.to_vec())); - } + success_claim.push((ft.to_vec(), receiver.clone(), amount)); + }, + Err(_) => failed_claim.push((ft.to_vec(), receiver.clone(), amount)), + }; } - Ok(success_claim) - } - - fn claim_reference( - sender: &Option, - tips_balance_info: &Self::TipsBalanceInfo, - reference_type: &Self::ReferenceType, - reference_id: &Self::ReferenceId, - account_id: &Option, - tx_fee: &Self::Balance, - verify_owner: bool, - ) -> Result { - let server_id = tips_balance_info.get_server_id(); - Self::verify_server(sender, server_id, verify_owner)?; - - if account_id.is_none() { - return Err(Error::::ReceiverNotExists) - } - - if tips_balance_info.get_ft_identifier() != "native".as_bytes() { - return Err(Error::::FtNotExists) + if success_claim.is_empty() { + return Err(Error::::NothingToClaimed) } - let native_info = TipsBalanceInfo::new(server_id, reference_type, reference_id, b"native"); - let result = Self::get_tips_balance(&native_info); - - if let Some(tips_balance) = result.clone() { - let amount = tips_balance.get_amount(); - - if amount == &Zero::zero() { - return Err(Error::::FailedToVerify) - } - - if amount < tx_fee { - return Err(Error::::FailedToVerify) - } - } else { - return Err(Error::::FailedToVerify) + if failed_claim.is_empty() { + return Ok((sender, (success_claim, None))) } - match CurrencyOf::::withdraw( - &Self::tipping_account_id(), - *tx_fee, - WithdrawReasons::TRANSFER, - ExistenceRequirement::KeepAlive, - ) { - Ok(imb) => { - CurrencyOf::::resolve_creating(sender.as_ref().unwrap(), imb); - - let ref_type = tips_balance_info.get_reference_type(); - let ref_id = tips_balance_info.get_reference_id(); - let ft_identifier = tips_balance_info.get_ft_identifier(); - let ft_identifiers = if "native".as_bytes() == ft_identifier { - vec![ft_identifier.to_vec()] - } else { - vec![b"native".to_vec(), ft_identifier.to_vec()] - }; - - let tips_balances = Self::update_tips_balances( - server_id, - &References::new(ref_type, &[ref_id.to_vec()]), - &References::new(reference_type, &[reference_id.to_vec()]), - &ft_identifiers, - &account_id.clone().unwrap(), - tx_fee, - &result.unwrap(), - ); - - Ok(tips_balances) - }, - _ => Err(Error::::BadSignature), - } + Ok((sender, (success_claim, Some(failed_claim)))) } - fn batch_claim_reference( - sender: &T::AccountId, + fn claim_reference( + receiver: &T::AccountId, server_id: &Self::ServerId, references: &Self::References, main_references: &Self::References, ft_identifiers: &Self::FtIdentifiers, account_id: &T::AccountId, tx_fee: &Self::Balance, - verify_owner: bool, - ) -> Result { - if sender == account_id { - return Err(Error::::FailedToVerify) - } - - Self::verify_server(&Some(sender.clone()), server_id, verify_owner)?; + ) -> Result { + let ref_type = main_references.get_reference_type().clone(); + let ref_ids = main_references.get_reference_ids().clone(); - if tx_fee == &Zero::zero() { + if ref_ids.len() != 1 { return Err(Error::::FailedToVerify) } - if main_references.get_reference_ids().len() != 1 { + if receiver == account_id { return Err(Error::::FailedToVerify) } - let ref_type = main_references.get_reference_type(); - let ref_id = &main_references.get_reference_ids()[0]; - let native_info = TipsBalanceInfo::new(server_id, ref_type, ref_id, b"native"); - let result = Self::get_tips_balance(&native_info); + Self::do_server_exist(server_id, Some(receiver))?; - if let Some(tips_balance) = result.clone() { - let amount = tips_balance.get_amount(); - - if amount == &Zero::zero() { - return Err(Error::::FailedToVerify) - } - - if amount < tx_fee { - return Err(Error::::FailedToVerify) - } - } else { - return Err(Error::::FailedToVerify) - } - - match CurrencyOf::::withdraw( - &Self::tipping_account_id(), - *tx_fee, - WithdrawReasons::TRANSFER, - ExistenceRequirement::KeepAlive, - ) { - Ok(imb) => { - CurrencyOf::::resolve_creating(sender, imb); - - let tips_balances = Self::update_tips_balances( - server_id, - references, - main_references, - ft_identifiers, - account_id, - tx_fee, - &result.unwrap(), - ); - - Ok(tips_balances) - }, - _ => Err(Error::::BadSignature), - } - } - - fn verify_social_media( - sender: &T::AccountId, - server_id: &Self::ServerId, - access_token: &Self::AccessToken, - social_media_credential: &Self::SocialMediaCredential, - ft_identifier: &Self::FtIdentifier, - ) -> Result<(), Self::Error> { - if !Self::is_integer(ft_identifier) { - return Err(Error::::WrongFormat) - } - - if ft_identifier != "native".as_bytes() { - return Err(Error::::FtNotExists) - } - - match Self::get_api_url(server_id, "/user-social-medias/verify") { - Ok(api_url) => { - let mut bearer = "Bearer ".as_bytes().to_vec(); - bearer.append(&mut access_token.to_vec()); - - let mut address = String::from("0x"); - address.push_str(&hex::encode(&sender.encode())); - - let username = social_media_credential.get_username(); - let platform = social_media_credential.get_platform(); - let body = json!({ - "address": &address, - "username": str::from_utf8(username).unwrap_or("username"), - "platform": str::from_utf8(platform).unwrap_or("platform"), - }) - .to_string(); - - let payload = Payload::>::init(server_id, &api_url, &bearer) - .set_body(body.as_bytes()) - .set_account_id(sender) - .set_ft_identifier(ft_identifier) - .set_payload_type(PayloadType::Create); - - let key = Self::derived_key(>::block_number()); - let data = IndexingData::init(b"verify_social_media", payload); - - offchain_index::set(&key, &data.encode()); - - Ok(()) - }, - Err(err) => Err(err), - } - } - - fn connect_account( - sender: &T::AccountId, - server_id: &Self::ServerId, - access_token: &Self::AccessToken, - user_credential: &Self::UserCredential, - ft_identifier: &Self::FtIdentifier, - ) -> Result<(), Self::Error> { - if !Self::is_integer(ft_identifier) { - return Err(Error::::WrongFormat) - } - - if ft_identifier != "native".as_bytes() { - return Err(Error::::FtNotExists) - } - - let user_id = user_credential.get_user_id(); - let result = str::from_utf8(user_id); - if result.is_err() { - return Err(Error::::WrongFormat) - } - - let mut endpoint = String::from("/users/"); - endpoint.push_str(result.unwrap()); - endpoint.push_str("/wallets"); - - match Self::get_api_url(server_id, &endpoint) { - Ok(api_url) => { - let mut bearer = "Bearer ".as_bytes().to_vec(); - bearer.append(&mut access_token.to_vec()); - - let mut address = String::from("0x"); - address.push_str(&hex::encode(&sender.encode())); - - let nonce = *user_credential.get_nonce(); - let mut signature = "0x".as_bytes().to_vec(); - signature.append(&mut user_credential.get_signature().to_vec()); - - let body = json!({ - "nonce": nonce, - "publicAddress": &address, - "signature": str::from_utf8(&signature).unwrap_or("signature"), - "walletType": "polkadot{.js}", - "networkType": "myriad", - "data": { - "id": &address, - }, - }) - .to_string(); - - let payload = Payload::>::init(server_id, &api_url, &bearer) - .set_body(body.as_bytes()) - .set_account_id(sender) - .set_ft_identifier(ft_identifier) - .set_payload_type(PayloadType::Connect); - - let key = Self::derived_key(>::block_number()); - let data = IndexingData::init(b"connect_account", payload); - - offchain_index::set(&key, &data.encode()); - - Ok(()) - }, - Err(err) => Err(err), - } + let sender = Self::tipping_account_id(); + let ref_id = (&ref_ids[0]).clone(); + let tips_balance_key = (server_id.clone(), ref_type, ref_id, b"native".to_vec()); + + Self::can_pay_fee(&tips_balance_key, tx_fee)?; + Self::do_transfer(b"native", &sender, receiver, *tx_fee)?; + + let tips_balances = Self::do_store_tips_balances( + server_id, + references, + main_references, + ft_identifiers, + account_id, + tx_fee, + ); + + Ok(tips_balances) } } diff --git a/pallets/tipping/src/interface.rs b/pallets/tipping/src/interface.rs index 0e86b9a..f8c0b13 100644 --- a/pallets/tipping/src/interface.rs +++ b/pallets/tipping/src/interface.rs @@ -1,78 +1,37 @@ -#[allow(clippy::too_many_arguments)] - pub trait TippingInterface { type Error; type TipsBalanceInfo; + type TipsBalanceKey; type Balance; - type TipsBalance; - type TipsBalances; - type UserCredential; - type SocialMediaCredential; type ServerId; type References; type ReferenceType; type ReferenceId; - type ReferenceIds; type FtIdentifier; - type AccessToken; - type DataId; - type DataType; type FtIdentifiers; - type FtIdentifierBalances; + type SendTipResult; + type ClaimTipResult; + type ClaimReferenceResult; fn send_tip( sender: &T::AccountId, tips_balance_info: &Self::TipsBalanceInfo, amount: &Self::Balance, - ) -> Result; + ) -> Result; fn claim_tip( receiver: &T::AccountId, - tips_balance_info: &Self::TipsBalanceInfo, - ) -> Result<(Self::Balance, Self::FtIdentifier), Self::Error>; - - fn batch_claim_tip( - receiver: &T::AccountId, - server_id: &Self::ServerId, - reference_type: &Self::ReferenceType, - reference_id: &Self::ReferenceId, + tips_balance_key: &Self::TipsBalanceKey, ft_identifiers: &Self::FtIdentifiers, - ) -> Result; + ) -> Result; fn claim_reference( - sender: &Option, - tips_balance_info: &Self::TipsBalanceInfo, - reference_type: &Self::ReferenceType, - reference_id: &Self::ReferenceId, - account_id: &Option, - tx_fee: &Self::Balance, - verify_owner: bool, - ) -> Result; - - fn batch_claim_reference( - sender: &T::AccountId, + receiver: &T::AccountId, server_id: &Self::ServerId, references: &Self::References, main_references: &Self::References, ft_identifiers: &Self::FtIdentifiers, account_id: &T::AccountId, tx_fee: &Self::Balance, - verify_owner: bool, - ) -> Result; - - fn verify_social_media( - sender: &T::AccountId, - server_id: &Self::ServerId, - access_token: &Self::AccessToken, - social_media_credential: &Self::SocialMediaCredential, - ft_identifier: &Self::FtIdentifier, - ) -> Result<(), Self::Error>; - - fn connect_account( - sender: &T::AccountId, - server_id: &Self::ServerId, - access_token: &Self::AccessToken, - user_credential: &Self::UserCredential, - ft_identifier: &Self::FtIdentifier, - ) -> Result<(), Self::Error>; + ) -> Result; } diff --git a/pallets/tipping/src/lib.rs b/pallets/tipping/src/lib.rs index 1937a35..8268391 100644 --- a/pallets/tipping/src/lib.rs +++ b/pallets/tipping/src/lib.rs @@ -10,7 +10,6 @@ pub use pallet::*; pub use pallet_server::interface::{ServerInfo, ServerProvider}; pub use scale_info::{prelude::string::*, TypeInfo}; -pub mod crypto; pub mod functions; pub mod impl_tipping; pub mod interface; @@ -18,7 +17,7 @@ pub mod types; pub mod weights; pub use crate::interface::TippingInterface; -pub use types::{api_response::*, payload::*, tips_balance::*}; +pub use types::*; pub use weights::WeightInfo; /// The current storage version. @@ -31,25 +30,21 @@ pub mod pallet { use frame_support::{ dispatch::DispatchResultWithPostInfo, pallet_prelude::*, - sp_runtime::{ - traits::Zero, - transaction_validity::{InvalidTransaction, TransactionValidity}, - }, - traits::Currency, - }; - use frame_system::{ - offchain::{AppCrypto, CreateSignedTransaction}, - pallet_prelude::*, + traits::{tokens::fungibles, Currency}, }; + use frame_system::pallet_prelude::*; use sp_std::vec::Vec; #[pallet::config] - pub trait Config: CreateSignedTransaction> + frame_system::Config { - /// The identifier type for an offchain worker. - type AuthorityId: AppCrypto; + pub trait Config: frame_system::Config { type Call: From>; type Event: From> + IsType<::Event>; type Currency: Currency<::AccountId>; + type Assets: fungibles::Mutate< + ::AccountId, + AssetId = AssetId, + Balance = AssetBalance, + >; type Server: ServerProvider; type WeightInfo: WeightInfo; } @@ -75,20 +70,12 @@ pub mod pallet { #[pallet::event] #[pallet::generate_deposit(pub(super) fn deposit_event)] pub enum Event { - /// Send tip success. [who, pot, tips_balance] - SendTip(T::AccountId, T::AccountId, TipsBalanceOf), - /// Claim tip success. [pot, who, amount, ft_identifier] - ClaimTip(T::AccountId, T::AccountId, BalanceOf, FtIdentifier), - /// Batch claim tip success [pot, who, Vec<(amount, ft_identifier)>] - BatchClaimTip(T::AccountId, T::AccountId, Vec<(BalanceOf, FtIdentifier)>), + /// Send tip success. [who, pot, (data, balance)] + SendTip(T::AccountId, T::AccountId, (TipsBalanceKey, BalanceOf)), + /// Claim tip success [pot, (succeed, failed)] + ClaimTip(T::AccountId, (AccountBalancesOf, Option>)), /// Claim reference success. [Vec] ClaimReference(Vec>), - /// Verify social media [status, Option] - VerifyingSocialMedia(Status, Option), - /// Connect account [status, Option] - ConnectingAccount(Status, Option), - /// Verify reference [status, Option] - VerifyingReference(Status), } #[pallet::error] @@ -98,28 +85,12 @@ pub mod pallet { NothingToClaimed, Unauthorized, ServerNotRegister, - ReceiverNotExists, - FtNotExists, - FtMustEmpty, - NotExists, WrongFormat, FailedToVerify, } #[pallet::hooks] - impl Hooks> for Pallet { - fn offchain_worker(block_number: T::BlockNumber) { - let verified = Self::verify_social_media_and_send_unsigned(block_number); - - if let Ok(Some(log_info)) = verified { - log::info!("Log: {} in blocknumber {:?}", log_info, block_number); - } - - if let Err(err) = verified { - log::info!("Error: {:?} in blocknumber {:?}", err, block_number); - } - } - } + impl Hooks> for Pallet {} #[pallet::call] impl Pallet { @@ -130,11 +101,10 @@ pub mod pallet { amount: BalanceOf, ) -> DispatchResultWithPostInfo { let sender = ensure_signed(origin)?; - let receiver = Self::tipping_account_id(); match >::send_tip(&sender, &tips_balance_info, &amount) { - Ok(tips_balance) => { - Self::deposit_event(Event::SendTip(sender, receiver, tips_balance)); + Ok((receiver, data)) => { + Self::deposit_event(Event::SendTip(sender, receiver, data)); Ok(().into()) }, Err(error) => Err(error.into()), @@ -143,45 +113,27 @@ pub mod pallet { #[pallet::weight(T::WeightInfo::claim_tip())] pub fn claim_tip( - origin: OriginFor, - tips_balance_info: TipsBalanceInfo, - ) -> DispatchResultWithPostInfo { - let sender = Self::tipping_account_id(); - let receiver = ensure_signed(origin)?; - - match >::claim_tip(&receiver, &tips_balance_info) { - Ok(result) => { - Self::deposit_event(Event::ClaimTip(sender, receiver, result.0, result.1)); - Ok(().into()) - }, - Err(error) => Err(error.into()), - } - } - - #[pallet::weight(T::WeightInfo::batch_claim_tip())] - pub fn batch_claim_tip( origin: OriginFor, server_id: ServerId, reference_type: ReferenceType, reference_id: ReferenceId, ft_identifiers: Vec, ) -> DispatchResultWithPostInfo { - let sender = Self::tipping_account_id(); let receiver = ensure_signed(origin)?; let mut ft_identifiers = ft_identifiers; ft_identifiers.sort_unstable(); ft_identifiers.dedup(); - match >::batch_claim_tip( + let tips_balance_key = (server_id, reference_type, reference_id, b"".to_vec()); + + match >::claim_tip( &receiver, - &server_id, - &reference_type, - &reference_id, + &tips_balance_key, &ft_identifiers, ) { - Ok(result) => { - Self::deposit_event(Event::BatchClaimTip(sender, receiver, result)); + Ok((sender, data)) => { + Self::deposit_event(Event::ClaimTip(sender, data)); Ok(().into()) }, Err(error) => Err(error.into()), @@ -190,34 +142,6 @@ pub mod pallet { #[pallet::weight(T::WeightInfo::claim_reference())] pub fn claim_reference( - origin: OriginFor, - tips_balance_info: TipsBalanceInfo, - reference_type: ReferenceType, - reference_id: ReferenceId, - account_id: Option>, - tx_fee: BalanceOf, - ) -> DispatchResultWithPostInfo { - let who = ensure_signed(origin)?; - - match >::claim_reference( - &Some(who), - &tips_balance_info, - &reference_type, - &reference_id, - &account_id, - &tx_fee, - true, - ) { - Ok(tips_balances) => { - Self::deposit_event(Event::ClaimReference(tips_balances)); - Ok(().into()) - }, - Err(error) => Err(error.into()), - } - } - - #[pallet::weight(T::WeightInfo::batch_claim_reference())] - pub fn batch_claim_reference( origin: OriginFor, server_id: ServerId, references: References, @@ -232,7 +156,7 @@ pub mod pallet { ft_identifiers.sort_unstable(); ft_identifiers.dedup(); - match >::batch_claim_reference( + match >::claim_reference( &who, &server_id, &references, @@ -240,7 +164,6 @@ pub mod pallet { &ft_identifiers, &account_id, &tx_fee, - true, ) { Ok(tips_balances) => { Self::deposit_event(Event::ClaimReference(tips_balances)); @@ -249,177 +172,5 @@ pub mod pallet { Err(error) => Err(error.into()), } } - - #[pallet::weight(0)] - pub fn claim_reference_unsigned( - origin: OriginFor, - _block_number: T::BlockNumber, - payload_type: PayloadType, - api_response: APIResult>, - ) -> DispatchResultWithPostInfo { - ensure_none(origin)?; - - if api_response.get_data_type().is_none() { - let event: Option> = match payload_type { - PayloadType::Create => - Some(Event::::VerifyingSocialMedia(Status::Failed, None)), - PayloadType::Connect => - Some(Event::::ConnectingAccount(Status::Failed, None)), - PayloadType::Delete => None, - }; - - if let Some(failed_event) = event { - Self::deposit_event(failed_event); - } - - return Ok(().into()) - } - - let server_id = api_response.get_server_id(); - let ft_identifier = api_response.get_ft_identifier(); - let access_token = api_response.get_access_token(); - let account_id = api_response.get_account_id(); - let data_type = api_response.get_data_type().as_ref().unwrap(); - - let reference_type: ReferenceType; - let reference_id: ReferenceId; - let tips_balance_info = match data_type { - DataType::UserSocialMedia(user_social_media_info) => { - reference_type = "user".as_bytes().to_vec(); - reference_id = user_social_media_info.get_user_id().to_vec(); - - TipsBalanceInfo::new( - server_id, - "people".as_bytes(), - user_social_media_info.get_people_id(), - ft_identifier, - ) - }, - DataType::Wallet(wallet_info) => { - reference_type = "user".as_bytes().to_vec(); - reference_id = wallet_info.get_user_id().to_vec(); - - TipsBalanceInfo::new(server_id, &reference_type, &reference_id, ft_identifier) - }, - }; - - let result: Result, Error> = - match >::claim_reference( - &None, - &tips_balance_info, - &reference_type, - &reference_id, - account_id, - &Zero::zero(), - false, - ) { - Ok(tips_balance) => { - Self::deposit_event(Event::ClaimReference(tips_balance)); - - let succes_event = match data_type { - DataType::UserSocialMedia(user_social_media_info) => - Event::::VerifyingSocialMedia( - Status::Success, - Some(user_social_media_info.clone()), - ), - DataType::Wallet(wallet_info) => Event::::ConnectingAccount( - Status::Success, - Some(wallet_info.clone()), - ), - }; - - Ok(succes_event) - }, - Err(error) => Err(error), - }; - - match result { - Ok(success_event) => { - Self::deposit_event(success_event); - Ok(().into()) - }, - Err(_) => { - let stored = Self::store_deleted_payload(server_id, access_token, data_type); - - log::info!("Deleted data"); - - if let Err(err) = stored { - log::info!("{:?}", err); - Err(err.into()) - } else { - Ok(().into()) - } - }, - } - } - - #[pallet::weight(T::WeightInfo::claim_reference())] - pub fn verify_social_media( - origin: OriginFor, - server_id: Vec, - access_token: Vec, - social_media_credential: SocialMediaCredential, - ft_identifier: Vec, - ) -> DispatchResultWithPostInfo { - let who = ensure_signed(origin)?; - - match >::verify_social_media( - &who, - &server_id, - &access_token, - &social_media_credential, - &ft_identifier, - ) { - Ok(()) => { - Self::deposit_event(Event::VerifyingSocialMedia(Status::default(), None)); - Ok(().into()) - }, - Err(error) => Err(error.into()), - } - } - - #[pallet::weight(T::WeightInfo::claim_reference())] - pub fn connect_account( - origin: OriginFor, - server_id: Vec, - access_token: Vec, - user_credential: UserCredential, - ft_identifier: Vec, - ) -> DispatchResultWithPostInfo { - let who = ensure_signed(origin)?; - - match >::connect_account( - &who, - &server_id, - &access_token, - &user_credential, - &ft_identifier, - ) { - Ok(()) => { - Self::deposit_event(Event::ConnectingAccount(Status::default(), None)); - Ok(().into()) - }, - Err(error) => Err(error.into()), - } - } - } - - #[pallet::validate_unsigned] - impl ValidateUnsigned for Pallet { - type Call = Call; - - fn validate_unsigned(_source: TransactionSource, call: &Self::Call) -> TransactionValidity { - match call { - Call::claim_reference_unsigned { - block_number, - payload_type: _, - api_response: _, - } => Self::validate_transaction_parameters( - block_number, - b"submit_claim_reference_unsigned", - ), - _ => InvalidTransaction::Call.into(), - } - } } } diff --git a/pallets/tipping/src/mock.rs b/pallets/tipping/src/mock.rs index be0d59a..31a817d 100644 --- a/pallets/tipping/src/mock.rs +++ b/pallets/tipping/src/mock.rs @@ -1,5 +1,8 @@ use crate as pallet_tipping; -use frame_support::{construct_runtime, parameter_types, traits::Everything}; +use frame_support::{ + construct_runtime, parameter_types, + traits::{Everything, GenesisBuild}, +}; use frame_system as system; use pallet_balances::AccountData; use sp_core::{ @@ -8,8 +11,8 @@ use sp_core::{ }; use sp_io::TestExternalities; use sp_runtime::{ - testing::{Header, TestXt}, - traits::{BlakeTwo256, Extrinsic as ExtrinsicT, IdentifyAccount, IdentityLookup, Verify}, + testing::Header, + traits::{BlakeTwo256, IdentifyAccount, IdentityLookup, Verify}, }; type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; @@ -25,6 +28,7 @@ construct_runtime!( Balances: pallet_balances::{Pallet, Call, Storage, Config, Event}, Tipping: pallet_tipping::{Pallet, Call, Storage, Event}, Server: pallet_server::{Pallet, Call, Storage, Event}, + Assets: pallet_assets::{Pallet, Call, Storage, Event}, } ); @@ -82,11 +86,11 @@ impl pallet_balances::Config for Test { } impl pallet_tipping::Config for Test { - type AuthorityId = pallet_tipping::crypto::TestAuthId; type Call = Call; type Event = Event; type Currency = Balances; type Server = Server; + type Assets = Assets; type WeightInfo = (); } @@ -95,34 +99,33 @@ impl pallet_server::Config for Test { type WeightInfo = (); } -type Extrinsic = TestXt; -type AccountId = <::Signer as IdentifyAccount>::AccountId; +pub type OctopusAssetId = u32; +pub type OctopusAssetBalance = u128; -impl frame_system::offchain::SigningTypes for Test { - type Public = ::Signer; - type Signature = Signature; +parameter_types! { + pub const ApprovalDeposit: Balance = 1; + pub const AssetDeposit: Balance = 1; + pub const MetadataDepositBase: Balance = 1; + pub const MetadataDepositPerByte: Balance = 1; + pub const StringLimit: u32 = 50; } -impl frame_system::offchain::SendTransactionTypes for Test -where - Call: From, -{ - type OverarchingCall = Call; - type Extrinsic = Extrinsic; -} +type AccountId = <::Signer as IdentifyAccount>::AccountId; -impl system::offchain::CreateSignedTransaction for Test -where - Call: From, -{ - fn create_transaction>( - call: Call, - _public: ::Signer, - _account: AccountId, - nonce: u64, - ) -> Option<(Call, ::SignaturePayload)> { - Some((call, (nonce, ()))) - } +impl pallet_assets::Config for Test { + type Event = Event; + type Balance = OctopusAssetBalance; + type AssetId = OctopusAssetId; + type Currency = Balances; + type ForceOrigin = frame_system::EnsureRoot; + type AssetDeposit = AssetDeposit; + type MetadataDepositBase = MetadataDepositBase; + type MetadataDepositPerByte = MetadataDepositPerByte; + type ApprovalDeposit = ApprovalDeposit; + type StringLimit = StringLimit; + type Freezer = (); + type Extra = (); + type WeightInfo = (); } pub fn account_key(s: &str) -> sr25519::Public { @@ -145,6 +148,32 @@ impl ExternalityBuilder { let satoshi_public = account_key("satoshi"); let admin_public = account_key("admin"); + pallet_assets::GenesisConfig:: { + assets: vec![(1, alice_public, true, 1), (2, alice_public, true, 1)], + metadata: vec![ + (1, b"DeBio".to_vec(), b"DBIO".to_vec(), 18), + (2, b"Doge".to_vec(), b"DOGE".to_vec(), 18), + ], + accounts: vec![ + (1, alice_public, 10), + (1, bob_public, 20), + (1, john_public, 30), + (1, satoshi_public, 40), + (1, admin_public, 50), + (2, alice_public, 10), + (2, bob_public, 20), + (2, john_public, 30), + (2, satoshi_public, 40), + (2, admin_public, 50), + ], + } + .assimilate_storage(&mut t) + .unwrap(); + + pallet_server::GenesisConfig:: { admin_key: admin_public } + .assimilate_storage(&mut t) + .unwrap(); + pallet_balances::GenesisConfig:: { balances: vec![ (alice_public, 10), diff --git a/pallets/tipping/src/tests.rs b/pallets/tipping/src/tests.rs index 303ae56..dee2359 100644 --- a/pallets/tipping/src/tests.rs +++ b/pallets/tipping/src/tests.rs @@ -1,40 +1,29 @@ use crate::{mock::*, Error, References, TipsBalance, TipsBalanceInfo}; -use frame_support::{ - assert_noop, assert_ok, - sp_runtime::{traits::Zero, SaturatedConversion}, -}; -use pallet_server::AdminKey; +use frame_support::{assert_noop, assert_ok, sp_runtime::traits::Zero}; #[test] fn send_tip_myria_works() { ::default().existential_deposit(2).build().execute_with(|| { - AdminKey::::put(account_key("admin")); - assert_ok!(Server::register( Origin::signed(account_key("admin")), account_key("alice"), - "myriad".as_bytes().to_vec(), - "myriad".as_bytes().to_vec(), - "https://api.dev.myriad.social".as_bytes().to_vec(), - "https://app.dev.myriad.social".as_bytes().to_vec(), + b"myriad".to_vec(), + b"myriad".to_vec(), + b"https://api.dev.myriad.social".to_vec(), + b"https://app.dev.myriad.social".to_vec(), )); - let tips_balance_info = TipsBalanceInfo::new( - "myriad".as_bytes(), - "people".as_bytes(), - "people_id".as_bytes(), - "native".as_bytes(), - ); - let tips_balance = TipsBalance::new(&tips_balance_info, &None, &1); + let tips_balance_info = TipsBalanceInfo::new(b"myriad", b"people", b"people_id", b"native"); + let tips_balance = TipsBalance::new(&tips_balance_info, &1); assert_ok!(Tipping::send_tip(Origin::signed(account_key("bob")), tips_balance_info, 1)); assert_eq!( Tipping::tips_balance_by_reference(( - "myriad".as_bytes().to_vec(), - "people".as_bytes().to_vec(), - "people_id".as_bytes().to_vec(), - "native".as_bytes().to_vec() + b"myriad".to_vec(), + b"people".to_vec(), + b"people_id".to_vec(), + b"native".to_vec() )), Some(tips_balance) ); @@ -44,301 +33,235 @@ fn send_tip_myria_works() { } #[test] -fn claim_reference_works() { +fn send_tip_assets_works() { ::default().existential_deposit(2).build().execute_with(|| { - AdminKey::::put(account_key("admin")); - assert_ok!(Server::register( Origin::signed(account_key("admin")), account_key("alice"), - "myriad".as_bytes().to_vec(), - "myriad".as_bytes().to_vec(), - "https://api.dev.myriad.social".as_bytes().to_vec(), - "https://app.dev.myriad.social".as_bytes().to_vec(), - )); - - let tips_balance_info = TipsBalanceInfo::new( - "myriad".as_bytes(), - "people".as_bytes(), - "people_id".as_bytes(), - "native".as_bytes(), - ); - - assert_ok!(Tipping::send_tip( - Origin::signed(account_key("bob")), - tips_balance_info.clone(), - 1 - )); - - let main_tips_balance_info = TipsBalanceInfo::new( - "myriad".as_bytes(), - "user".as_bytes(), - "user_id".as_bytes(), - "native".as_bytes(), - ); - - assert_ok!(Tipping::send_tip( - Origin::signed(account_key("bob")), - main_tips_balance_info.clone(), - 1 - )); - - assert_ok!(Tipping::claim_reference( - Origin::signed(account_key("alice")), - tips_balance_info.clone(), - "user".as_bytes().to_vec(), - "user_id".as_bytes().to_vec(), - Some(account_key("john")), - 1u128.saturated_into(), + b"myriad".to_vec(), + b"myriad".to_vec(), + b"https://api.dev.myriad.social".to_vec(), + b"https://app.dev.myriad.social".to_vec(), )); - let main_tips_balance = - TipsBalance::new(&main_tips_balance_info, &Some(account_key("john")), &1); - - assert_eq!( - Tipping::tips_balance_by_reference(( - "myriad".as_bytes().to_vec(), - "user".as_bytes().to_vec(), - "user_id".as_bytes().to_vec(), - "native".as_bytes().to_vec() - )), - Some(main_tips_balance) - ); + let tips_balance_info = + TipsBalanceInfo::new(b"myriad", b"people", b"people_id", "1".as_bytes()); + let tips_balance = TipsBalance::new(&tips_balance_info, &1); - let tips_balance = TipsBalance::new(&tips_balance_info, &None, &0); + assert_ok!(Tipping::send_tip(Origin::signed(account_key("bob")), tips_balance_info, 1)); assert_eq!( Tipping::tips_balance_by_reference(( - "myriad".as_bytes().to_vec(), - "people".as_bytes().to_vec(), - "people_id".as_bytes().to_vec(), - "native".as_bytes().to_vec() + b"myriad".to_vec(), + b"people".to_vec(), + b"people_id".to_vec(), + "1".as_bytes().to_vec() )), Some(tips_balance) ); - assert_eq!(Balances::free_balance(account_key("alice")), 11); + assert_eq!(Assets::balance(1, account_key("bob")), 19); }) } #[test] -fn batch_claim_reference_works() { +fn claim_reference_works() { ::default().existential_deposit(2).build().execute_with(|| { - AdminKey::::put(account_key("admin")); - assert_ok!(Server::register( Origin::signed(account_key("admin")), account_key("alice"), - "myriad".as_bytes().to_vec(), - "myriad".as_bytes().to_vec(), - "https://api.dev.myriad.social".as_bytes().to_vec(), - "https://app.dev.myriad.social".as_bytes().to_vec(), + b"myriad".to_vec(), + b"myriad".to_vec(), + b"https://api.dev.myriad.social".to_vec(), + b"https://app.dev.myriad.social".to_vec(), )); - let tips_balance_info = TipsBalanceInfo::new( - "myriad".as_bytes(), - "people".as_bytes(), - "people_id".as_bytes(), - "native".as_bytes(), - ); - let mut tips_balance = TipsBalance::new(&tips_balance_info, &None, &1); + let tips_balance_info_0 = + TipsBalanceInfo::new(b"myriad", b"people", b"people_id", b"native"); + let tips_balance_info_1 = + TipsBalanceInfo::new(b"myriad", b"people", b"people_id", "1".as_bytes()); + let tips_balance_info_2 = + TipsBalanceInfo::new(b"myriad", b"people", b"people_id", "2".as_bytes()); - let main_tips_balance_info = TipsBalanceInfo::new( - "myriad".as_bytes(), - "user".as_bytes(), - "user_id".as_bytes(), - "native".as_bytes(), - ); + let mut tips_balance_0 = TipsBalance::new(&tips_balance_info_0, &1); + let mut tips_balance_1 = TipsBalance::new(&tips_balance_info_1, &1); + let mut tips_balance_2 = TipsBalance::new(&tips_balance_info_2, &2); - let mut main_tips_balance = TipsBalance::new(&main_tips_balance_info, &None, &1); + let main_tips_balance_info_0 = + TipsBalanceInfo::new(b"myriad", b"user", b"user_id", b"native"); - assert_ok!(Tipping::send_tip(Origin::signed(account_key("bob")), tips_balance_info, 1)); + let main_tips_balance_info_1 = TipsBalanceInfo::new(b"myriad", b"user", b"user_id", b"1"); + + let main_tips_balance_info_2 = TipsBalanceInfo::new(b"myriad", b"user", b"user_id", b"2"); + + let mut main_tips_balance_0 = TipsBalance::new(&main_tips_balance_info_0, &1); + let mut main_tips_balance_1 = TipsBalance::new(&main_tips_balance_info_1, &1); + let mut main_tips_balance_2 = TipsBalance::new(&main_tips_balance_info_2, &2); + + assert_ok!(Tipping::send_tip(Origin::signed(account_key("bob")), tips_balance_info_0, 1)); + assert_ok!(Tipping::send_tip(Origin::signed(account_key("bob")), tips_balance_info_1, 1)); + assert_ok!(Tipping::send_tip(Origin::signed(account_key("bob")), tips_balance_info_2, 2)); assert_ok!(Tipping::send_tip( Origin::signed(account_key("bob")), - main_tips_balance_info, + main_tips_balance_info_0, 1 )); - assert_ok!(Tipping::batch_claim_reference( + assert_ok!(Tipping::claim_reference( Origin::signed(account_key("alice")), - "myriad".as_bytes().to_vec(), + b"myriad".to_vec(), References::new(b"people", &[b"people_id".to_vec()]), References::new(b"user", &[b"user_id".to_vec()]), - vec![b"native".to_vec()], + vec![b"native".to_vec(), b"1".to_vec(), b"2".to_vec()], account_key("john"), 1, )); - tips_balance.set_amount(Zero::zero()); - main_tips_balance.set_account_id(&Some(account_key("john"))); + tips_balance_0.set_amount(Zero::zero()); + tips_balance_1.set_amount(Zero::zero()); + tips_balance_2.set_amount(Zero::zero()); + main_tips_balance_0.set_account_id(&account_key("john")); + main_tips_balance_1.set_account_id(&account_key("john")); + main_tips_balance_2.set_account_id(&account_key("john")); assert_eq!( Tipping::tips_balance_by_reference(( - "myriad".as_bytes().to_vec(), - "people".as_bytes().to_vec(), - "people_id".as_bytes().to_vec(), - "native".as_bytes().to_vec() + b"myriad".to_vec(), + b"people".to_vec(), + b"people_id".to_vec(), + b"native".to_vec() )), - Some(tips_balance.clone()) + Some(tips_balance_0.clone()) ); assert_eq!( Tipping::tips_balance_by_reference(( - "myriad".as_bytes().to_vec(), - "user".as_bytes().to_vec(), - "user_id".as_bytes().to_vec(), - "native".as_bytes().to_vec() + b"myriad".to_vec(), + b"people".to_vec(), + b"people_id".to_vec(), + b"1".to_vec() )), - Some(main_tips_balance.clone()) + Some(tips_balance_1.clone()) ); - assert_eq!(Balances::free_balance(account_key("alice")), 11); - }) -} - -#[test] -pub fn claim_tip_works() { - ::default().existential_deposit(2).build().execute_with(|| { - AdminKey::::put(account_key("admin")); - - assert_ok!(Server::register( - Origin::signed(account_key("admin")), - account_key("alice"), - "myriad".as_bytes().to_vec(), - "myriad".as_bytes().to_vec(), - "https://api.dev.myriad.social".as_bytes().to_vec(), - "https://app.dev.myriad.social".as_bytes().to_vec(), - )); - - let tips_balance_info = TipsBalanceInfo::new( - "myriad".as_bytes(), - "people".as_bytes(), - "people_id".as_bytes(), - "native".as_bytes(), + assert_eq!( + Tipping::tips_balance_by_reference(( + b"myriad".to_vec(), + b"people".to_vec(), + b"people_id".to_vec(), + b"2".to_vec() + )), + Some(tips_balance_2.clone()) ); - assert_ok!(Tipping::send_tip( - Origin::signed(account_key("bob")), - tips_balance_info.clone(), - 1 - )); - - let main_tips_balance_info = TipsBalanceInfo::new( - "myriad".as_bytes(), - "user".as_bytes(), - "user_id".as_bytes(), - "native".as_bytes(), + assert_eq!( + Tipping::tips_balance_by_reference(( + b"myriad".to_vec(), + b"user".to_vec(), + b"user_id".to_vec(), + b"native".to_vec() + )), + Some(main_tips_balance_0.clone()) ); - assert_ok!(Tipping::send_tip( - Origin::signed(account_key("bob")), - main_tips_balance_info.clone(), - 1 - )); - - assert_ok!(Tipping::claim_reference( - Origin::signed(account_key("alice")), - tips_balance_info, - "user".as_bytes().to_vec(), - "user_id".as_bytes().to_vec(), - Some(account_key("john")), - 1u128.saturated_into(), - )); + assert_eq!( + Tipping::tips_balance_by_reference(( + b"myriad".to_vec(), + b"user".to_vec(), + b"user_id".to_vec(), + b"1".to_vec() + )), + Some(main_tips_balance_1.clone()) + ); - assert_ok!(Tipping::claim_tip(Origin::signed(account_key("john")), main_tips_balance_info)); + assert_eq!( + Tipping::tips_balance_by_reference(( + b"myriad".to_vec(), + b"user".to_vec(), + b"user_id".to_vec(), + b"2".to_vec() + )), + Some(main_tips_balance_2.clone()) + ); - assert_eq!(Balances::free_balance(account_key("john")), 31); assert_eq!(Balances::free_balance(account_key("alice")), 11); }) } #[test] -pub fn batch_claim_tip_works() { +pub fn claim_tip_works() { ::default().existential_deposit(2).build().execute_with(|| { - AdminKey::::put(account_key("admin")); - assert_ok!(Server::register( Origin::signed(account_key("admin")), account_key("alice"), - "myriad".as_bytes().to_vec(), - "myriad".as_bytes().to_vec(), - "https://api.dev.myriad.social".as_bytes().to_vec(), - "https://app.dev.myriad.social".as_bytes().to_vec(), + b"myriad".to_vec(), + b"myriad".to_vec(), + b"https://api.dev.myriad.social".to_vec(), + b"https://app.dev.myriad.social".to_vec(), )); - let tips_balance_info = TipsBalanceInfo::new( - "myriad".as_bytes(), - "people".as_bytes(), - "people_id".as_bytes(), - "native".as_bytes(), - ); - - assert_ok!(Tipping::send_tip( - Origin::signed(account_key("bob")), - tips_balance_info.clone(), - 1 - )); + let tips_balance_info_0 = + TipsBalanceInfo::new(b"myriad", b"people", b"people_id", b"native"); + let tips_balance_info_1 = + TipsBalanceInfo::new(b"myriad", b"people", b"people_id", "1".as_bytes()); + let tips_balance_info_2 = + TipsBalanceInfo::new(b"myriad", b"people", b"people_id", "2".as_bytes()); - let main_tips_balance_info = TipsBalanceInfo::new( - "myriad".as_bytes(), - "user".as_bytes(), - "user_id".as_bytes(), - "native".as_bytes(), - ); + let main_tips_balance_info_0 = + TipsBalanceInfo::new(b"myriad", b"user", b"user_id", b"native"); + assert_ok!(Tipping::send_tip(Origin::signed(account_key("bob")), tips_balance_info_0, 1)); + assert_ok!(Tipping::send_tip(Origin::signed(account_key("bob")), tips_balance_info_1, 1)); + assert_ok!(Tipping::send_tip(Origin::signed(account_key("bob")), tips_balance_info_2, 2)); assert_ok!(Tipping::send_tip( Origin::signed(account_key("bob")), - main_tips_balance_info, + main_tips_balance_info_0, 1 )); assert_ok!(Tipping::claim_reference( Origin::signed(account_key("alice")), - tips_balance_info, - "user".as_bytes().to_vec(), - "user_id".as_bytes().to_vec(), - Some(account_key("john")), - 1u128.saturated_into(), + b"myriad".to_vec(), + References::new(b"people", &[b"people_id".to_vec()]), + References::new(b"user", &[b"user_id".to_vec()]), + vec![b"native".to_vec(), b"1".to_vec(), b"2".to_vec()], + account_key("john"), + 1, )); - assert_ok!(Tipping::batch_claim_tip( + assert_ok!(Tipping::claim_tip( Origin::signed(account_key("john")), b"myriad".to_vec(), b"user".to_vec(), b"user_id".to_vec(), - vec![b"native".to_vec()] + vec![b"native".to_vec(), b"1".to_vec(), b"2".to_vec()] )); assert_eq!(Balances::free_balance(account_key("john")), 31); assert_eq!(Balances::free_balance(account_key("alice")), 11); + assert_eq!(Assets::balance(1, account_key("john")), 31); + assert_eq!(Assets::balance(2, account_key("john")), 32); }) } #[test] fn cant_send_tip_myria_when_insufficient_balance() { ::default().existential_deposit(2).build().execute_with(|| { - AdminKey::::put(account_key("admin")); - assert_ok!(Server::register( Origin::signed(account_key("admin")), account_key("alice"), - "myriad".as_bytes().to_vec(), - "myriad".as_bytes().to_vec(), - "https://api.dev.myriad.social".as_bytes().to_vec(), - "https://app.dev.myriad.social".as_bytes().to_vec(), + b"myriad".to_vec(), + b"myriad".to_vec(), + b"https://api.dev.myriad.social".to_vec(), + b"https://app.dev.myriad.social".to_vec(), )); - let tips_balance_info = TipsBalanceInfo::new( - "myriad".as_bytes(), - "people".as_bytes(), - "people_id".as_bytes(), - "native".as_bytes(), - ); + let tips_balance_info = TipsBalanceInfo::new(b"myriad", b"people", b"people_id", b"native"); assert_noop!( Tipping::send_tip(Origin::signed(account_key("bob")), tips_balance_info, 21), - Error::::InsufficientBalance + Error::::BadSignature ); }) } @@ -346,12 +269,7 @@ fn cant_send_tip_myria_when_insufficient_balance() { #[test] fn cant_send_tip_myria_when_server_id_not_register() { ::default().existential_deposit(2).build().execute_with(|| { - let tips_balance_info = TipsBalanceInfo::new( - "myriad".as_bytes(), - "people".as_bytes(), - "people_id".as_bytes(), - "native".as_bytes(), - ); + let tips_balance_info = TipsBalanceInfo::new(b"myriad", b"people", b"people_id", b"native"); assert_noop!( Tipping::send_tip(Origin::signed(account_key("alice")), tips_balance_info, 1), @@ -363,12 +281,7 @@ fn cant_send_tip_myria_when_server_id_not_register() { #[test] fn cant_send_tip_myria_when_ft_identifier_exists() { ::default().existential_deposit(2).build().execute_with(|| { - let tips_balance_info = TipsBalanceInfo::new( - "myriad".as_bytes(), - "people".as_bytes(), - "people_id".as_bytes(), - "native".as_bytes(), - ); + let tips_balance_info = TipsBalanceInfo::new(b"myriad", b"people", b"people_id", b"native"); assert_noop!( Tipping::send_tip(Origin::signed(account_key("alice")), tips_balance_info, 1,), @@ -380,113 +293,10 @@ fn cant_send_tip_myria_when_ft_identifier_exists() { #[test] fn cant_claim_reference_when_server_not_registered() { ::default().existential_deposit(2).build().execute_with(|| { - let tips_balance_info = TipsBalanceInfo::new( - "myriad".as_bytes(), - "people".as_bytes(), - "people_id".as_bytes(), - "native".as_bytes(), - ); - assert_noop!( Tipping::claim_reference( Origin::signed(account_key("alice")), - tips_balance_info, - "user".as_bytes().to_vec(), - "user_id".as_bytes().to_vec(), - None, - 1u128.saturated_into(), - ), - Error::::ServerNotRegister, - ); - }) -} - -#[test] -fn cant_claim_reference_when_not_as_server_owner() { - ::default().existential_deposit(2).build().execute_with(|| { - AdminKey::::put(account_key("admin")); - - assert_ok!(Server::register( - Origin::signed(account_key("admin")), - account_key("alice"), - "myriad".as_bytes().to_vec(), - "myriad".as_bytes().to_vec(), - "https://api.dev.myriad.social".as_bytes().to_vec(), - "https://app.dev.myriad.social".as_bytes().to_vec(), - )); - - let tips_balance_info = TipsBalanceInfo::new( - "myriad".as_bytes(), - "people".as_bytes(), - "people_id".as_bytes(), - "native".as_bytes(), - ); - - assert_noop!( - Tipping::claim_reference( - Origin::signed(account_key("bob")), - tips_balance_info, - "user".as_bytes().to_vec(), - "user_id".as_bytes().to_vec(), - None, - 1u128.saturated_into(), - ), - Error::::Unauthorized, - ); - }) -} - -#[test] -fn cant_claim_reference_when_receiver_not_exists() { - ::default().existential_deposit(2).build().execute_with(|| { - AdminKey::::put(account_key("admin")); - - assert_ok!(Server::register( - Origin::signed(account_key("admin")), - account_key("alice"), - "myriad".as_bytes().to_vec(), - "myriad".as_bytes().to_vec(), - "https://api.dev.myriad.social".as_bytes().to_vec(), - "https://app.dev.myriad.social".as_bytes().to_vec(), - )); - - let mut tips_balance_info = TipsBalanceInfo::new( - "myriad".as_bytes(), - "people".as_bytes(), - "people_id".as_bytes(), - "native".as_bytes(), - ); - - assert_ok!(Tipping::send_tip( - Origin::signed(account_key("bob")), - tips_balance_info.clone(), - 1 - )); - - tips_balance_info.set_reference_type("user".as_bytes()); - tips_balance_info.set_reference_id("user_id".as_bytes()); - - assert_noop!( - Tipping::claim_reference( - Origin::signed(account_key("alice")), - tips_balance_info, - "user".as_bytes().to_vec(), - "user_id".as_bytes().to_vec(), - None, - 1u128.saturated_into(), - ), - Error::::ReceiverNotExists, - ); - }) -} - -#[test] -fn cant_batch_claim_reference_when_not_server_not_register() { - ::default().existential_deposit(2).build().execute_with(|| { - assert_noop!( - Tipping::batch_claim_reference( - Origin::signed(account_key("alice")), - "myriad".as_bytes().to_vec(), + b"myriad".to_vec(), References::new(b"people", &[b"people_id".to_vec()]), References::new(b"user", &[b"user_id".to_vec()]), vec![b"native".to_vec()], @@ -499,61 +309,48 @@ fn cant_batch_claim_reference_when_not_server_not_register() { } #[test] -fn cant_batch_claim_reference_when_not_server_owner() { +fn cant_claim_reference_when_not_as_server_owner() { ::default().existential_deposit(2).build().execute_with(|| { - AdminKey::::put(account_key("admin")); - assert_ok!(Server::register( Origin::signed(account_key("admin")), account_key("alice"), - "myriad".as_bytes().to_vec(), - "myriad".as_bytes().to_vec(), - "https://api.dev.myriad.social".as_bytes().to_vec(), - "https://app.dev.myriad.social".as_bytes().to_vec(), - )); - - assert_ok!(Server::register( - Origin::signed(account_key("admin")), - account_key("satoshi"), - "myriad_1".as_bytes().to_vec(), - "myriad_1".as_bytes().to_vec(), - "https://api.dev.myriad.social".as_bytes().to_vec(), - "https://app.dev.myriad.social".as_bytes().to_vec(), + b"myriad".to_vec(), + b"myriad".to_vec(), + b"https://api.dev.myriad.social".to_vec(), + b"https://app.dev.myriad.social".to_vec(), )); assert_noop!( - Tipping::batch_claim_reference( - Origin::signed(account_key("alice")), - "myriad_1".as_bytes().to_vec(), + Tipping::claim_reference( + Origin::signed(account_key("john")), + b"myriad".to_vec(), References::new(b"people", &[b"people_id".to_vec()]), References::new(b"user", &[b"user_id".to_vec()]), vec![b"native".to_vec()], account_key("alice"), 1, ), - Error::::FailedToVerify, + Error::::Unauthorized, ); }) } #[test] -fn cant_batch_claim_reference() { +fn cant_claim_reference() { ::default().existential_deposit(2).build().execute_with(|| { - AdminKey::::put(account_key("admin")); - assert_ok!(Server::register( Origin::signed(account_key("admin")), account_key("alice"), - "myriad".as_bytes().to_vec(), - "myriad".as_bytes().to_vec(), - "https://api.dev.myriad.social".as_bytes().to_vec(), - "https://app.dev.myriad.social".as_bytes().to_vec(), + b"myriad".to_vec(), + b"myriad".to_vec(), + b"https://api.dev.myriad.social".to_vec(), + b"https://app.dev.myriad.social".to_vec(), )); assert_noop!( - Tipping::batch_claim_reference( + Tipping::claim_reference( Origin::signed(account_key("alice")), - "myriad".as_bytes().to_vec(), + b"myriad".to_vec(), References::new(b"people", &[b"people_id".to_vec()]), References::new(b"user", &[b"user_id".to_vec()]), vec![b"native".to_vec()], @@ -564,9 +361,9 @@ fn cant_batch_claim_reference() { ); assert_noop!( - Tipping::batch_claim_reference( + Tipping::claim_reference( Origin::signed(account_key("alice")), - "myriad".as_bytes().to_vec(), + b"myriad".to_vec(), References::new(b"people", &[b"people_id".to_vec()]), References::new(b"user", &[b"user_id".to_vec()]), vec![b"native".to_vec()], @@ -577,9 +374,9 @@ fn cant_batch_claim_reference() { ); assert_noop!( - Tipping::batch_claim_reference( + Tipping::claim_reference( Origin::signed(account_key("alice")), - "myriad".as_bytes().to_vec(), + b"myriad".to_vec(), References::new(b"people", &[b"people_id".to_vec()]), References::new(b"user", &[b"user_id".to_vec(), b"user_idd".to_vec()]), vec![b"native".to_vec()], @@ -590,9 +387,9 @@ fn cant_batch_claim_reference() { ); assert_noop!( - Tipping::batch_claim_reference( + Tipping::claim_reference( Origin::signed(account_key("alice")), - "myriad".as_bytes().to_vec(), + b"myriad".to_vec(), References::new(b"people", &[b"people_id".to_vec()]), References::new(b"user", &[b"user_id".to_vec()]), vec![b"native".to_vec()], @@ -602,12 +399,8 @@ fn cant_batch_claim_reference() { Error::::FailedToVerify, ); - let main_tips_balance_info = TipsBalanceInfo::new( - "myriad".as_bytes(), - "user".as_bytes(), - "user_id".as_bytes(), - "native".as_bytes(), - ); + let main_tips_balance_info = + TipsBalanceInfo::new(b"myriad", b"user", b"user_id", b"native"); assert_ok!(Tipping::send_tip( Origin::signed(account_key("bob")), @@ -616,9 +409,9 @@ fn cant_batch_claim_reference() { )); assert_noop!( - Tipping::batch_claim_reference( + Tipping::claim_reference( Origin::signed(account_key("alice")), - "myriad".as_bytes().to_vec(), + b"myriad".to_vec(), References::new(b"people", &[b"people_id".to_vec()]), References::new(b"user", &[b"user_id".to_vec()]), vec![b"native".to_vec()], @@ -635,9 +428,9 @@ fn cant_batch_claim_reference() { )); assert_noop!( - Tipping::batch_claim_reference( + Tipping::claim_reference( Origin::signed(account_key("alice")), - "myriad".as_bytes().to_vec(), + b"myriad".to_vec(), References::new(b"people", &[b"people_id".to_vec()]), References::new(b"user", &[b"user_id".to_vec()]), vec![b"native".to_vec()], @@ -652,135 +445,55 @@ fn cant_batch_claim_reference() { #[test] fn cant_claim_tip_balance_when_nothing_to_claimed() { ::default().existential_deposit(2).build().execute_with(|| { - assert_noop!( - Tipping::claim_tip( - Origin::signed(account_key("alice")), - TipsBalanceInfo::new( - "myriad".as_bytes(), - "user".as_bytes(), - "user_id".as_bytes(), - "native".as_bytes() - ), - ), - Error::::NotExists, - ); - - AdminKey::::put(account_key("admin")); - assert_ok!(Server::register( Origin::signed(account_key("admin")), account_key("alice"), - "myriad".as_bytes().to_vec(), - "myriad".as_bytes().to_vec(), - "https://api.dev.myriad.social".as_bytes().to_vec(), - "https://app.dev.myriad.social".as_bytes().to_vec(), - )); - - let tips_balance_info = TipsBalanceInfo::new( - "myriad".as_bytes(), - "user".as_bytes(), - "user_id".as_bytes(), - "native".as_bytes(), - ); - - assert_ok!(Tipping::send_tip( - Origin::signed(account_key("bob")), - tips_balance_info.clone(), - 0 + b"myriad".to_vec(), + b"myriad".to_vec(), + b"https://api.dev.myriad.social".to_vec(), + b"https://app.dev.myriad.social".to_vec(), )); assert_noop!( - Tipping::claim_tip(Origin::signed(account_key("alice")), tips_balance_info,), + Tipping::claim_tip( + Origin::signed(account_key("alice")), + b"server".to_vec(), + b"user".to_vec(), + b"user_id".to_vec(), + vec![b"native".to_vec()], + ), Error::::NothingToClaimed, ); }) } -#[test] -fn cant_claim_tip_balance_when_unauthorized() { - ::default().existential_deposit(2).build().execute_with(|| { - AdminKey::::put(account_key("admin")); - - assert_ok!(Server::register( - Origin::signed(account_key("admin")), - account_key("alice"), - "myriad".as_bytes().to_vec(), - "myriad".as_bytes().to_vec(), - "https://api.dev.myriad.social".as_bytes().to_vec(), - "https://app.dev.myriad.social".as_bytes().to_vec(), - )); - - let tips_balance_info = TipsBalanceInfo::new( - "myriad".as_bytes(), - "user".as_bytes(), - "user_id".as_bytes(), - "native".as_bytes(), - ); - - assert_ok!(Tipping::send_tip( - Origin::signed(account_key("bob")), - tips_balance_info.clone(), - 1 - )); - - assert_ok!(Tipping::claim_reference( - Origin::signed(account_key("alice")), - tips_balance_info.clone(), - "user".as_bytes().to_vec(), - "user_id".as_bytes().to_vec(), - Some(account_key("john")), - 1u128.saturated_into(), - )); - - assert_noop!( - Tipping::claim_tip(Origin::signed(account_key("satoshi")), tips_balance_info,), - Error::::Unauthorized - ); - }) -} - #[test] fn call_event_should_work() { ::default().existential_deposit(2).build().execute_with(|| { - AdminKey::::put(account_key("admin")); - assert_ok!(Server::register( Origin::signed(account_key("admin")), account_key("alice"), - "myriad".as_bytes().to_vec(), - "myriad".as_bytes().to_vec(), - "https://api.dev.myriad.social".as_bytes().to_vec(), - "https://app.dev.myriad.social".as_bytes().to_vec(), + b"myriad".to_vec(), + b"myriad".to_vec(), + b"https://api.dev.myriad.social".to_vec(), + b"https://app.dev.myriad.social".to_vec(), )); - let tips_balance_info = TipsBalanceInfo::new( - "myriad".as_bytes(), - "people".as_bytes(), - "people_id".as_bytes(), - "native".as_bytes(), - ); - let tips_balance = TipsBalance::new(&tips_balance_info, &None, &1); + let tips_balance_info = TipsBalanceInfo::new(b"myriad", b"people", b"people_id", b"native"); + let tips_balance_key = tips_balance_info.key(); - assert_ok!(Tipping::send_tip( - Origin::signed(account_key("bob")), - tips_balance_info.clone(), - 1 - )); + assert_ok!(Tipping::send_tip(Origin::signed(account_key("bob")), tips_balance_info, 1)); let tipping_account_id = Tipping::tipping_account_id(); System::assert_last_event(Event::Tipping(crate::Event::SendTip( account_key("bob"), tipping_account_id, - tips_balance, + (tips_balance_key, 1), ))); - let main_tips_balance_info = TipsBalanceInfo::new( - "myriad".as_bytes(), - "user".as_bytes(), - "user_id".as_bytes(), - "native".as_bytes(), - ); + let main_tips_balance_info = + TipsBalanceInfo::new(b"myriad", b"user", b"user_id", b"native"); assert_ok!(Tipping::send_tip( Origin::signed(account_key("bob")), @@ -790,23 +503,7 @@ fn call_event_should_work() { assert_ok!(Tipping::claim_reference( Origin::signed(account_key("alice")), - tips_balance_info, - "user".as_bytes().to_vec(), - "user_id".as_bytes().to_vec(), - Some(account_key("john")), - 1u128.saturated_into(), - )); - - let main_tips_balance = - TipsBalance::new(&main_tips_balance_info, &Some(account_key("john")), &1); - - System::assert_last_event(Event::Tipping(crate::Event::ClaimReference(vec![ - main_tips_balance, - ]))); - - assert_ok!(Tipping::batch_claim_reference( - Origin::signed(account_key("alice")), - "myriad".as_bytes().to_vec(), + b"myriad".to_vec(), References::new(b"people", &[b"people_id".to_vec()]), References::new(b"user", &[b"user_id".to_vec()]), vec![b"native".to_vec()], @@ -814,35 +511,34 @@ fn call_event_should_work() { 1, )); - let main_tips_balance = - TipsBalance::new(&main_tips_balance_info, &Some(account_key("john")), &0); + let mut main_tips_balance = TipsBalance::new(&main_tips_balance_info, &1); + + main_tips_balance.set_account_id(&account_key("john")); System::assert_last_event(Event::Tipping(crate::Event::ClaimReference(vec![ main_tips_balance, ]))); - let main_tips_balance_info = TipsBalanceInfo::new( - "myriad".as_bytes(), - "user".as_bytes(), - "user_id".as_bytes(), - "native".as_bytes(), - ); + let main_tips_balance_info = + TipsBalanceInfo::new(b"myriad", b"user", b"user_id", b"native"); assert_ok!(Tipping::send_tip( Origin::signed(account_key("bob")), - main_tips_balance_info.clone(), + main_tips_balance_info, 1 )); - assert_ok!( - Tipping::claim_tip(Origin::signed(account_key("john")), main_tips_balance_info,) - ); + assert_ok!(Tipping::claim_tip( + Origin::signed(account_key("john")), + b"myriad".to_vec(), + b"user".to_vec(), + b"user_id".to_vec(), + vec![b"native".to_vec()], + )); System::assert_last_event(Event::Tipping(crate::Event::ClaimTip( tipping_account_id, - account_key("john"), - 1, - "native".as_bytes().to_vec(), + (vec![(b"native".to_vec(), account_key("john"), 2)], None), ))); }) } diff --git a/pallets/tipping/src/types/tips_balance.rs b/pallets/tipping/src/types.rs similarity index 74% rename from pallets/tipping/src/types/tips_balance.rs rename to pallets/tipping/src/types.rs index b9c33cb..f1a2d9e 100644 --- a/pallets/tipping/src/types/tips_balance.rs +++ b/pallets/tipping/src/types.rs @@ -1,6 +1,6 @@ use crate::*; -use frame_support::{pallet_prelude::*, traits::Currency}; +use frame_support::{pallet_prelude::*, sp_runtime::traits::Saturating, traits::Currency}; use sp_std::vec::Vec; pub type ServerId = Vec; @@ -8,6 +8,15 @@ pub type FtIdentifier = Vec; pub type ReferenceId = Vec; pub type ReferenceType = Vec; +pub type TipsBalanceKey = (ServerId, ReferenceType, ReferenceId, FtIdentifier); +pub type TipsBalanceTuppleOf = (TipsBalanceKey, BalanceOf); + +pub type AccountBalancesOf = Vec<(FtIdentifier, AccountIdOf, BalanceOf)>; +pub type AccountBalancesTuppleOf = (AccountBalancesOf, Option>); + +pub type AssetId = u32; +pub type AssetBalance = u128; + pub type AccountIdOf = ::AccountId; pub type CurrencyOf = ::Currency; pub type BalanceOf = as Currency>>::Balance; @@ -19,19 +28,19 @@ pub struct TipsBalance { account_id: Option, amount: Balance, } -impl TipsBalance { - pub fn new( - tips_balance_info: &TipsBalanceInfo, - account_id: &Option, - amount: &Balance, - ) -> Self { +impl TipsBalance { + pub fn new(tips_balance_info: &TipsBalanceInfo, amount: &Balance) -> Self { Self { tips_balance_info: tips_balance_info.clone(), - account_id: account_id.clone(), + account_id: None, amount: amount.clone(), } } + pub fn key(&self) -> TipsBalanceKey { + self.tips_balance_info.key() + } + pub fn get_tips_balance_info(&self) -> &TipsBalanceInfo { &self.tips_balance_info } @@ -68,8 +77,12 @@ impl TipsBalance { self.amount = amount; } - pub fn set_account_id(&mut self, account_id: &Option) { - self.account_id = account_id.clone(); + pub fn add_amount(&mut self, amount: Balance) { + self.amount = self.amount.clone().saturating_add(amount); + } + + pub fn set_account_id(&mut self, account_id: &AccountId) { + self.account_id = Some(account_id.clone()); } } @@ -95,6 +108,15 @@ impl TipsBalanceInfo { } } + pub fn key(&self) -> TipsBalanceKey { + ( + self.server_id.clone(), + self.reference_type.clone(), + self.reference_id.clone(), + self.ft_identifier.clone(), + ) + } + pub fn get_reference_id(&self) -> &Vec { &self.reference_id } diff --git a/pallets/tipping/src/types/api_response.rs b/pallets/tipping/src/types/api_response.rs deleted file mode 100644 index 3f66bf2..0000000 --- a/pallets/tipping/src/types/api_response.rs +++ /dev/null @@ -1,147 +0,0 @@ -use crate::*; - -use frame_support::pallet_prelude::*; -use serde::{Deserialize, Deserializer}; -use sp_std::vec::Vec; - -#[derive(Encode, Decode, Clone, Default, RuntimeDebug, PartialEq, Eq, TypeInfo)] -pub struct APIResult( - ServerId, - FtIdentifier, - AccessToken, - Option, - Option, -); -impl APIResult { - pub fn init(server_id: &[u8], ft_identifier: &[u8], access_token: &[u8]) -> Self { - Self(server_id.to_vec(), ft_identifier.to_vec(), access_token.to_vec(), None, None) - } - - pub fn get_server_id(&self) -> &Vec { - &self.0 - } - - pub fn get_ft_identifier(&self) -> &Vec { - &self.1 - } - - pub fn get_access_token(&self) -> &Vec { - &self.2 - } - - pub fn get_account_id(&self) -> &Option { - &self.3 - } - - pub fn get_data_type(&self) -> &Option { - &self.4 - } - - pub fn set_account_id(mut self, account_id: Option) -> Self { - self.3 = account_id; - self - } - - pub fn set_data_type(mut self, data_type: Option) -> Self { - self.4 = data_type; - self - } -} - -#[derive(Deserialize, Encode, Decode, Default, RuntimeDebug, TypeInfo, Clone, Eq, PartialEq)] -pub struct UserSocialMedia { - #[serde(deserialize_with = "de_string_to_bytes")] - id: Vec, - #[serde(deserialize_with = "de_string_to_bytes")] - platform: Vec, - #[serde(deserialize_with = "de_string_to_bytes")] - created_at: Vec, - #[serde(deserialize_with = "de_string_to_bytes")] - updated_at: Vec, - #[serde(deserialize_with = "de_string_to_bytes")] - user_id: Vec, - #[serde(deserialize_with = "de_string_to_bytes")] - people_id: Vec, - primary: bool, - verified: bool, -} -impl UserSocialMedia { - pub fn get_id(&self) -> &Vec { - &self.id - } - - pub fn get_people_id(&self) -> &Vec { - &self.people_id - } - - pub fn get_user_id(&self) -> &Vec { - &self.user_id - } -} - -#[derive(Deserialize, Encode, Decode, Default, RuntimeDebug, TypeInfo, Clone, Eq, PartialEq)] -pub struct Wallet { - #[serde(deserialize_with = "de_string_to_bytes")] - id: Vec, - #[serde(deserialize_with = "de_string_to_bytes")] - created_at: Vec, - #[serde(deserialize_with = "de_string_to_bytes")] - updated_at: Vec, - #[serde(deserialize_with = "de_string_to_bytes")] - user_id: Vec, - #[serde(deserialize_with = "de_string_to_bytes")] - network_id: Vec, - primary: bool, -} -impl Wallet { - pub fn get_id(&self) -> &Vec { - &self.id - } - - pub fn get_user_id(&self) -> &Vec { - &self.user_id - } -} - -pub fn de_string_to_bytes<'de, D>(de: D) -> Result, D::Error> -where - D: Deserializer<'de>, -{ - let s: &str = Deserialize::deserialize(de)?; - Ok(s.as_bytes().to_vec()) -} - -#[derive(Encode, Decode, Clone, RuntimeDebug, PartialEq, Eq, TypeInfo, Default)] -pub struct UserCredential { - nonce: u64, - signature: Vec, - user_id: Vec, -} -impl UserCredential { - pub fn get_nonce(&self) -> &u64 { - &self.nonce - } - - pub fn get_signature(&self) -> &Vec { - &self.signature - } - - pub fn get_user_id(&self) -> &Vec { - &self.user_id - } -} - -#[derive(Encode, Decode, Clone, RuntimeDebug, PartialEq, Eq, TypeInfo, Default)] -pub struct SocialMediaCredential { - username: Vec, - platform: Vec, -} -impl SocialMediaCredential { - pub fn get_username(&self) -> &Vec { - &self.username - } - - pub fn get_platform(&self) -> &Vec { - &self.platform - } -} diff --git a/pallets/tipping/src/types/mod.rs b/pallets/tipping/src/types/mod.rs deleted file mode 100644 index ceb8803..0000000 --- a/pallets/tipping/src/types/mod.rs +++ /dev/null @@ -1,3 +0,0 @@ -pub mod api_response; -pub mod payload; -pub mod tips_balance; diff --git a/pallets/tipping/src/types/payload.rs b/pallets/tipping/src/types/payload.rs deleted file mode 100644 index 063f06d..0000000 --- a/pallets/tipping/src/types/payload.rs +++ /dev/null @@ -1,113 +0,0 @@ -use crate::*; - -use frame_support::pallet_prelude::*; -use sp_std::vec::Vec; - -pub type AccessToken = Vec; - -#[derive(Encode, Decode, Clone, RuntimeDebug, PartialEq, Eq, TypeInfo)] -pub enum DataType { - UserSocialMedia(UserSocialMedia), - Wallet(Wallet), -} -impl Default for DataType { - fn default() -> Self { - DataType::UserSocialMedia(UserSocialMedia::default()) - } -} - -#[derive(Encode, Decode, Clone, RuntimeDebug, PartialEq, Eq, TypeInfo)] -pub enum PayloadType { - Create, - Connect, - Delete, -} -impl Default for PayloadType { - fn default() -> Self { - PayloadType::Delete - } -} - -#[derive(Encode, Decode, Clone, Default, RuntimeDebug, PartialEq, Eq, TypeInfo)] -pub struct Payload { - server_id: Vec, - api_url: Vec, - body: Vec, - access_token: Vec, - account_id: Option, - ft_identifier: Vec, - payload_type: PayloadType, -} -impl Payload { - pub fn init(server_id: &[u8], api_url: &[u8], access_token: &[u8]) -> Self { - Self { - server_id: server_id.to_vec(), - api_url: api_url.to_vec(), - access_token: access_token.to_vec(), - body: Vec::new(), - account_id: None, - ft_identifier: b"native".to_vec(), - payload_type: PayloadType::default(), - } - } - - pub fn get_server_id(&self) -> &Vec { - &self.server_id - } - - pub fn get_api_url(&self) -> &Vec { - &self.api_url - } - - pub fn get_access_token(&self) -> &Vec { - &self.access_token - } - - pub fn get_body(&self) -> &Vec { - &self.body - } - - pub fn get_account_id(&self) -> &Option { - &self.account_id - } - - pub fn get_ft_identifier(&self) -> &Vec { - &self.ft_identifier - } - - pub fn get_payload_type(&self) -> &PayloadType { - &self.payload_type - } - - pub fn set_body(mut self, body: &[u8]) -> Self { - self.body = body.to_vec(); - self - } - - pub fn set_account_id(mut self, account_id: &AccountId) -> Self { - self.account_id = Some(account_id.clone()); - self - } - - pub fn set_ft_identifier(mut self, ft_identifier: &[u8]) -> Self { - self.ft_identifier = ft_identifier.to_vec(); - self - } - - pub fn set_payload_type(mut self, payload_type: PayloadType) -> Self { - self.payload_type = payload_type; - self - } -} - -#[derive(Encode, Decode, Clone, Default, RuntimeDebug, PartialEq, Eq, TypeInfo)] -pub struct IndexingData(Vec, Payload); -impl IndexingData { - pub fn get_payload(&self) -> &Payload { - &self.1 - } - - pub fn init(key_id: &[u8], payload: Payload) -> Self { - Self(key_id.to_vec(), payload) - } -} diff --git a/pallets/tipping/src/weights.rs b/pallets/tipping/src/weights.rs index a7c81a7..de9fa8a 100644 --- a/pallets/tipping/src/weights.rs +++ b/pallets/tipping/src/weights.rs @@ -1,7 +1,7 @@ //! Autogenerated weights for pallet_tipping //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-07-12, STEPS: `20`, REPEAT: 10, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-07-16, STEPS: `20`, REPEAT: 10, LOW RANGE: `[]`, HIGH RANGE: `[]` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 128 // Executed Command: @@ -27,22 +27,14 @@ use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; use sp_std::marker::PhantomData; /// Weight functions needed for pallet_tipping. -pub trait WeightInfo { - fn send_tip() -> Weight; - fn claim_reference() -> Weight; - fn batch_claim_reference() -> Weight; - fn claim_tip() -> Weight; - fn batch_claim_tip() -> Weight; -} +pub trait WeightInfo { fn send_tip() -> Weight; fn claim_reference() -> Weight; fn claim_tip() -> Weight;} /// Weights for pallet_tipping using the Substrate node and recommended hardware. -pub struct SubstrateWeight(PhantomData); -impl WeightInfo for SubstrateWeight { - // Storage: Server ServerById (r:1 w:0) +pub struct SubstrateWeight(PhantomData);impl WeightInfo for SubstrateWeight { + // Storage: Server ServerById (r:1 w:0) // Storage: System Account (r:1 w:0) // Storage: Tipping TipsBalanceByReference (r:1 w:1) - // Storage: System Account (r:1 w:0) fn send_tip() -> Weight { - 172_200_000_u64 + 368_800_000_u64 .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -50,29 +42,14 @@ impl WeightInfo for SubstrateWeight { // Storage: Tipping TipsBalanceByReference (r:2 w:2) // Storage: System Account (r:1 w:1) fn claim_reference() -> Weight { - 218_100_000_u64 - .saturating_add(T::DbWeight::get().reads(4_u64)) - .saturating_add(T::DbWeight::get().writes(3_u64)) - } - // Storage: Server ServerById (r:1 w:0) - // Storage: Tipping TipsBalanceByReference (r:2 w:2) - // Storage: System Account (r:1 w:1) - fn batch_claim_reference() -> Weight { - 215_800_000_u64 + 332_900_000_u64 .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } // Storage: Tipping TipsBalanceByReference (r:1 w:1) // Storage: System Account (r:1 w:1) fn claim_tip() -> Weight { - 137_000_000_u64 - .saturating_add(T::DbWeight::get().reads(2_u64)) - .saturating_add(T::DbWeight::get().writes(2_u64)) - } - // Storage: Tipping TipsBalanceByReference (r:1 w:1) - // Storage: System Account (r:1 w:1) - fn batch_claim_tip() -> Weight { - 136_700_000_u64 + 169_600_000_u64 .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -81,10 +58,10 @@ impl WeightInfo for SubstrateWeight { // For backwards compatibility and tests impl WeightInfo for () { // Storage: Server ServerById (r:1 w:0) - // Storage: Tipping TipsBalanceByReference (r:1 w:1) // Storage: System Account (r:1 w:0) + // Storage: Tipping TipsBalanceByReference (r:1 w:1) fn send_tip() -> Weight { - 172_200_000_u64 + 368_800_000_u64 .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -92,29 +69,14 @@ impl WeightInfo for () { // Storage: Tipping TipsBalanceByReference (r:2 w:2) // Storage: System Account (r:1 w:1) fn claim_reference() -> Weight { - 218_100_000_u64 - .saturating_add(RocksDbWeight::get().reads(4_u64)) - .saturating_add(RocksDbWeight::get().writes(3_u64)) - } - // Storage: Server ServerById (r:1 w:0) - // Storage: Tipping TipsBalanceByReference (r:2 w:2) - // Storage: System Account (r:1 w:1) - fn batch_claim_reference() -> Weight { - 215_800_000_u64 + 332_900_000_u64 .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } // Storage: Tipping TipsBalanceByReference (r:1 w:1) // Storage: System Account (r:1 w:1) fn claim_tip() -> Weight { - 137_000_000_u64 - .saturating_add(RocksDbWeight::get().reads(2_u64)) - .saturating_add(RocksDbWeight::get().writes(2_u64)) - } - // Storage: Tipping TipsBalanceByReference (r:1 w:1) - // Storage: System Account (r:1 w:1) - fn batch_claim_tip() -> Weight { - 136_700_000_u64 + 169_600_000_u64 .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } diff --git a/runtime/Cargo.toml b/runtime/Cargo.toml index 9126a76..7f3836e 100644 --- a/runtime/Cargo.toml +++ b/runtime/Cargo.toml @@ -1,6 +1,6 @@ [package] name = 'myriad-runtime' -version = '2.1.3' +version = '2.1.4' edition = '2021' license = 'AGPL-3.0' authors = ['Myriad Dev Team '] diff --git a/runtime/src/lib.rs b/runtime/src/lib.rs index ad69673..fde12a0 100644 --- a/runtime/src/lib.rs +++ b/runtime/src/lib.rs @@ -170,7 +170,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { // `spec_version`, and `authoring_version` are the same between Wasm and native. // This value is set to 100 to notify Polkadot-JS App (https://polkadot.js.org/apps) to use // the compatible custom types. - spec_version: 2013, + spec_version: 2014, impl_version: 1, apis: RUNTIME_API_VERSIONS, transaction_version: 1, @@ -664,10 +664,10 @@ impl pallet_server::Config for Runtime { } impl pallet_tipping::Config for Runtime { - type AuthorityId = pallet_tipping::crypto::TestAuthId; type Call = Call; type Event = Event; type Currency = Balances; + type Assets = OctopusAssets; type Server = Server; type WeightInfo = (); } @@ -702,7 +702,7 @@ construct_runtime!( // Local pallets Server: pallet_server::{Call, Event, Config, Pallet, Storage}, - Tipping: pallet_tipping::{Call, Event, Pallet, Storage, ValidateUnsigned}, + Tipping: pallet_tipping::{Call, Event, Pallet, Storage}, } );