diff --git a/bloc/types/bloctypes.mo b/bloc/types/bloctypes.mo index 1be837d2..e91084e9 100644 --- a/bloc/types/bloctypes.mo +++ b/bloc/types/bloctypes.mo @@ -5,6 +5,38 @@ import Ledgertypes "ledgertypes"; // import Principal module { + // New structs from Rust + public type PayoutDistribution = { + winner : Nat; + creator : Nat; + platform : Nat; + }; + + public type TournamentMeta = { + start_time : Text; + end_time : Text; + prize_pool : Nat; + winning_prize : Nat; + stream_url : ?Text; + description : Text; + tournament_banner : ?Text; + tags : [Text]; + }; + + public type TeamType = { #Duo; #Squad; #Solo }; + + public type Team = { + id : Text; + name : Text; + members : [Principal]; + captain : Principal; + created_at : Text; + metadata : ?Text; + }; + + public type UserMode = { #Base; #Creator; #Moderator }; + + public type OperationResult = { #Ok : Text; #Err : Text }; public type UserTrack = { user : Principal; @@ -96,6 +128,9 @@ module { losses : ?Nat8; points : ?[(Text, Text, Point)]; principal_id : Text; + tournaments : ?[Text]; + usermode : ?UserMode; + earnings : ?Nat; role : ?Role; squad_badge : Text; status : Status; @@ -104,6 +139,7 @@ module { wins : Nat8; referral_id : ?Text }; + public type Point = { position_points : Nat; @@ -126,6 +162,9 @@ module { captain : Text; status : SquadType; name : Text; + created_at : ?Text; + created_by : ?Principal; + participating_members : ParticipatingMember; wins : ?Nat8; losses : ?Nat8; attendance : ?Nat8; @@ -142,6 +181,11 @@ module { losses : Nat8; }; + public type ParticipatingMember = { + tournament_id: Text; + members : [Member]; + }; + public type Role = { #Player; #Mod; @@ -185,6 +229,18 @@ module { tournament_rules : Text; tournament_type : TournamentType; // mods : [Text]; + creator_principal : ?Principal; + is_private : ?Bool; + moderators : ?[Principal]; + payout_distribution : ?PayoutDistribution; + external_link : ?Text; + metadata : ?TournamentMeta; + is_team_based : ?Bool; + team_size : ?TeamType; + teams : ?[Team]; + allow_solo_players : ?Bool; + allow_auto_match : ?Bool; + referral_ids : ?[Text]; game : Text; squad : [Squad]; squad_points : ?[(Text, Text, Point)]; @@ -263,7 +319,13 @@ module { no_of_winners : ?Nat8; no_of_participants : Nat; game_type : GameType; - name : ?Text + name : ?Text; + creators_principal : ?Principal; + is_private : ?Bool; + moderators : ?[Principal]; + payout_distribution : ?PayoutDistribution; + external_link : ?Text; + metadata : ?TournamentMeta; }; public type LobbyStatus = { diff --git a/build.sh b/build.sh deleted file mode 100755 index ff06612d..00000000 --- a/build.sh +++ /dev/null @@ -1,160 +0,0 @@ -#!/bin/bash - -echo ">> Building ledger" - -dfx identity remove minter -dfx identity new minter -dfx identity use minter -MINT_ACC=$(dfx ledger account-id) -export MINT_ACC - -dfx identity use default - -export OWNER=$(dfx identity get-principal) - -LEDGER_ACC=$(dfx ledger account-id) -export LEDGER_ACC - -ARCHIVE_CONTROLLER=$(dfx identity get-principal) -export ARCHIVE_CONTROLLER - -export TOKEN_NAME="ICP" - - candid-extractor target/wasm32-unknown-unknown/release/game_bloc_backend.wasm > game_bloc_backend/game_bloc_backend.did - - -cargo build --release --target wasm32-unknown-unknown --package game_bloc_backend - -dfx deploy icp_ledger --argument "(variant {Init =record {minting_account = \"${MINT_ACC}\"; -initial_values = vec { record { \"${LEDGER_ACC}\"; -record { e8s=100_000_000_000 } } } ; archive_options = opt record {num_blocks_to_archive = 1000000; trigger_threshold = 1000000; \ - controller_id = principal \"${ARCHIVE_CONTROLLER}\"; }; send_whitelist = vec {}}})" --specified-id ryjl3-tyaaa-aaaaa-aaaba-cai - -dfx deploy icp_index --specified-id qhbym-qaaaa-aaaaa-aaafq-cai --argument '(record {ledger_id = principal "ryjl3-tyaaa-aaaaa-aaaba-cai"})' - -# dfx canister --network local call icp_ledger icr1_transfer ' -# (record { -# to=(record { -# owner=(principal "2vxsx-fae") -# }); -# amount=500_000_000 -# })' - -# dfx ledger transfer --amount 500_000 --memo 123 476653ac80a51b906bcc24f5ce59c1c6b4290d8dddc7ac6fae4a4b5070cf5abd - -# dfx identity use DevJourney -# dfx canister call icp_ledger icrc1_transfer "(record { to = record { owner = principal \"b77ix-eeaaa-aaaaa-qaada-cai\";};  amount = 1_000_000;})" - -# --specified-id ryjl3-tyaaa-aaaaa-aaaaa-cai -# dfx deploy --network local icrc1_ledger --argument ' -# (variant { -# Init = record { -# token_name = "Local ICP"; -# token_symbol = "LICP"; -# minting_account = record { -# owner = principal "'${OWNER}'"; -# }; -# initial_balances = vec { -# record { -# record { -# owner = principal "'${OWNER}'"; -# }; -# 100_000_000_000; -# }; -# }; -# metadata = vec {}; -# transfer_fee = 10; -# archive_options = record { -# trigger_threshold = 2000; -# num_blocks_to_archive = 1000; -# controller_id = principal "'${OWNER}'"; -# } -# } -# }) -# ' - -dfx deploy --network local --specified-id mxzaz-hqaaa-aaaar-qaada-cai ckbtc_ledger --argument ' - (variant { - Init = record { - token_name = "Local ckBTC"; - token_symbol = "LCKBTC"; - minting_account = record { - owner = principal "'${OWNER}'"; - }; - initial_balances = vec { - record { - record { - owner = principal "'${OWNER}'"; - }; - 100_000_000_000; - }; - }; - metadata = vec {}; - transfer_fee = 10; - archive_options = record { - trigger_threshold = 2000; - num_blocks_to_archive = 1000; - controller_id = principal "'${OWNER}'"; - } - } - }) -' - -# dfx deploy ckbtc_index --specified-id n5wcd-faaaa-aaaar-qaaea-cai --argument '(record {ledger_id = principal "mxzaz-hqaaa-aaaar-qaada-cai"})' - -dfx deploy --network local ckbtc_index --argument ' - record { - ledger_id = (principal "mxzaz-hqaaa-aaaar-qaada-cai"); - } -' - - -dfx deploy --network local --specified-id ss2fx-dyaaa-aaaar-qacoq-cai cketh_ledger --argument ' - (variant { - Init = record { - token_name = "Local ckETH"; - token_symbol = "LCKETH"; - minting_account = record { - owner = principal "'${OWNER}'"; - }; - initial_balances = vec { - record { - record { - owner = principal "'${OWNER}'"; - }; - 100_000_000_000; - }; - }; - metadata = vec {}; - transfer_fee = 10; - archive_options = record { - trigger_threshold = 2000; - num_blocks_to_archive = 1000; - controller_id = principal "'${OWNER}'"; - } - } - }) -' - -dfx deploy --network local cketh_index --argument ' - record { - ledger_id = (principal "ss2fx-dyaaa-aaaar-qacoq-cai"); - } -' - - -dfx deploy - -# "system_api": { -# "candid": "system_api/vetkd_system_api.did", -# "type": "rust", -# "package": "vetkd_system_api" -# }, - - -# dfx deploy --network=ic canister update-settings kitchen --add-controller ltmcx-2y32p-k3cxj-oe7mh-zplyh-mg7j2-w5756-qajf5-l6y47-be56z-nqe --network=ic2024-10-03 21:07:49.875732 UTC: [Canister bd3sg-teaaa-aaaaa-qaaba-cai] 20[ic-icrc1-index] Indexed: 0 waiting : 22 -# 4-10-03 21:07:49.875732 UTC: [Canister be2us-64aaa-aaaaa-qaabq-cai] - -# MOPS_VERSION=1.0.0 sh -ci "$(curl -fsSL cli.mops.one/install.sh | sh)" - -let diff --git a/game_bloc_backend/.idea/workspace.xml b/game_bloc_backend/.idea/workspace.xml index 32a5b2b3..2dae76d6 100644 --- a/game_bloc_backend/.idea/workspace.xml +++ b/game_bloc_backend/.idea/workspace.xml @@ -8,10 +8,10 @@ - - + + + - + + { "associatedIndex": 4 } @@ -51,7 +55,7 @@ "RunOnceActivity.ShowReadmeOnStart": "true", "RunOnceActivity.git.unshallow": "true", "RunOnceActivity.rust.reset.selective.auto.import": "true", - "git-widget-placeholder": "crowdfunded-to-wagr", + "git-widget-placeholder": "#37 on backend-calls-optimization", "last_opened_file_path": "/Users/ola/Documents/Github/Gamebloc-ICP/game_bloc_backend", "node.js.detected.package.eslint": "true", "node.js.detected.package.tslint": "true", @@ -97,6 +101,13 @@ + + + + + + + diff --git a/game_bloc_backend/game_bloc_backend.did b/game_bloc_backend/game_bloc_backend.did index baa29162..c818cd33 100644 --- a/game_bloc_backend/game_bloc_backend.did +++ b/game_bloc_backend/game_bloc_backend.did @@ -26,6 +26,15 @@ type LobbyAccount = record { type LobbyStatus = variant { GameInProgress; ReadyToStart; GameCompleted }; type Member = record { name : text; principal_id : text }; type ModTag = variant { Mod1; Mod2; Mod3 }; +type ParticipatingMember = record { + participating_squad_members : vec Member; + tournament_id : text; +}; +type PayoutDistribution = record { + creator : nat64; + winner : nat64; + platform : nat64; +}; type Point = record { kill_points : nat; total_points : nat; @@ -37,39 +46,61 @@ type Squad = record { tag : text; id_hash : text; status : SquadType; + participating_members : ParticipatingMember; members : vec Member; name : text; wins : opt nat8; losses : opt nat8; + created_at : opt text; + created_by : opt principal; attendance : opt nat8; captain : text; requests : vec text; points : opt vec record { text; text; Point }; }; type SquadType = variant { Open; Closed }; -type Status = variant { Online; Offline }; +type Status = variant { Away; Online; Offline }; +type Team = record { + id : text; + members : vec principal; + metadata : opt text; + name : text; + created_at : text; + captain : principal; +}; +type TeamType = variant { Duo; Squad; Solo }; type TournamentAccount = record { idx : nat8; id_hash : text; + max_teams : opt nat64; status : TournamentStatus; + external_link : opt text; + teams : opt vec Team; title : text; creator : text; entry_fee : opt nat; messages : opt vec Chat; creator_id : opt text; + metadata : opt TournamentMeta; game : text; + allow_auto_match : opt bool; user : vec text; in_game_names : opt vec record { text; text; text }; tournament_variation : opt Variation; winers : vec text; total_prize : nat; + is_team_based : opt bool; end_date : text; + is_private : opt bool; tournament_rules : text; ended : opt bool; squad_in_game_names : opt vec vec record { text; text; text }; + team_size : opt TeamType; squad : vec Squad; + payout_distribution : opt PayoutDistribution; accepts_wagers : opt bool; no_of_participants_at_bump : opt nat; + referal_ids : opt vec text; lobbies : opt vec LobbyAccount; game_type : text; user_details : opt vec UserProfile; @@ -82,6 +113,8 @@ type TournamentAccount = record { points_vector_mod_1 : opt vec record { text; text; Point }; points_vector_mod_2 : opt vec record { text; text; Point }; points_vector_mod_3 : opt vec record { text; text; Point }; + creator_principal : opt principal; + moderators : opt vec principal; no_of_winners : nat8; squad_vector_mod_1 : opt vec record { text; text; Point }; squad_vector_mod_2 : opt vec record { text; text; Point }; @@ -91,8 +124,19 @@ type TournamentAccount = record { entry_prize : nat8; points : opt vec record { text; text; Point }; squad_points : opt vec record { text; text; Point }; + allow_solo_players : opt bool; }; type TournamentLobbyType = variant { MultiLobby; SingleLobby }; +type TournamentMeta = record { + tags : vec text; + description : text; + tournament_banner : opt text; + end_time : text; + start_time : text; + stream_url : opt text; + prize_pool : nat64; + winning_prize : nat64; +}; type TournamentStatus = variant { AcceptingPlayers; GameInProgress; @@ -100,19 +144,23 @@ type TournamentStatus = variant { GameCompleted; }; type TournamentType = variant { Prepaid; Crowdfunded; Blitzkrieg }; +type UserMode = variant { Base; Moderator; Creator }; type UserProfile = record { age : nat8; account_id : text; id_hash : text; status : Status; referral_id : opt text; + usermode : opt UserMode; username : text; date : text; role : opt Role; canister_id : text; wins : nat8; + tournaments : opt vec text; losses : opt nat8; is_mod : bool; + earnings : opt nat; attendance : opt nat8; principal_id : text; squad_badge : text; diff --git a/game_bloc_backend/src/model.rs b/game_bloc_backend/src/model.rs index 403511ad..f5bd5aa9 100644 --- a/game_bloc_backend/src/model.rs +++ b/game_bloc_backend/src/model.rs @@ -1,4 +1,5 @@ use std::borrow::Cow; +use crate::*; use candid::{CandidType, Decode, Deserialize, Encode}; use ic_stable_structures::{storable::Bound, Storable}; @@ -27,8 +28,11 @@ pub_struct!(UserProfile { tournaments_created:u8, points: Option>, username: String, + tournaments: Option>, //deprecated is_mod: bool, + usermode: Option, + earnings: Option, role: Option, principal_id: String, account_id : String, @@ -37,6 +41,8 @@ pub_struct!(UserProfile { referral_id: Option, }); + + pub_struct!( TournamentAccount { id_hash: String, @@ -44,6 +50,20 @@ pub_struct!( creator_id: Option, status: TournamentStatus, idx: u8, + creator_principal: Option, + + is_private: Option, + moderators: Option>, + payout_distribution: Option, + external_link: Option, + metadata: Option, + is_team_based: Option, + team_size: Option, + teams: Option>, + max_teams: Option, + allow_solo_players: Option, + allow_auto_match: Option, + starting_date: String, tournament_rules: String, tournament_type: TournamentType, @@ -52,6 +72,7 @@ pub_struct!( squad_in_game_names:Option>>, messages: Option>, user: Vec, + referal_ids: Option>, user_details: Option>, winers: Vec, //deprecated @@ -142,6 +163,7 @@ pub_struct!(Point { total_points: u128, }); + pub_struct!( Squad { id_hash: String, @@ -153,8 +175,17 @@ pub_struct!( attendance: Option, losses: Option, members: Vec, + participating_members: ParticipatingMember, requests: Vec, points: Option>, + created_at: Option, + created_by: Option, +}); + +pub_struct!( + ParticipatingMember { + tournament_id: String, + participating_squad_members: Vec, }); pub_struct!(Member { @@ -188,6 +219,7 @@ pub enum Status { #[default] Online, Offline, + Away, } #[derive(Clone, Debug, Default, CandidType, Deserialize, Serialize)] @@ -195,6 +227,7 @@ pub enum Role { #[default] Player, Mod, + // Admin, TribunalMod(ModTag), } @@ -302,3 +335,156 @@ impl Storable for UserProfile { is_fixed_size: false, }; } + + +/// Error messages +#[derive(Debug, Serialize, Deserialize)] +pub enum ErrorMessage { + NotAuthorized, + DoesNotExist, + Expired, + WrongCredentials, + NotAllowed, + NotEnoughBalance, + NotEligible, +} + +/// Notification model +#[derive(Debug, Serialize, Deserialize)] +pub struct Notification { + pub id: u64, + pub title: String, + pub body: String, + pub user: Principal, + pub username: String, + pub date: String, + pub read: bool, +} + +/// Container for multiple notifications +#[derive(Debug, Serialize, Deserialize)] +pub struct Notifications { + pub notifications: Vec, + pub user: Principal, +} + +/// User modes +#[derive( + Clone, Debug, PartialEq, Default, Ord, Eq, PartialOrd, CandidType, Deserialize, Serialize, +)] +pub enum UserMode { + #[default] + Base, + Creator, + Moderator, +} + +/// Tournament identifier +pub type TournamentId = String; + +/// Payout distribution among parties +#[derive( + Clone, Debug, PartialEq, Default, Ord, Eq, PartialOrd, CandidType, Deserialize, Serialize, +)] +pub struct PayoutDistribution { + pub winner: u64, + pub creator: u64, + pub platform: u64, +} + +/// Various game types +// #[derive(Debug, Serialize, Deserialize)] +// pub enum GameType { +// Board, +// Card, +// Shooter, +// MOBA, +// Sports, +// Trivia, +// Arcade, +// Custom(String), +// } + +/// Different game modes +// #[derive(Debug, Serialize, Deserialize)] +// pub enum GameMode { +// OnevOne, +// FreeForAll, +// BracketElimination, +// League, +// TimedScore, +// LastManStanding, +// GroupToFinals, +// Custom(String), +// } + +/// Metadata for tournaments +#[derive( + Clone, Debug, PartialEq, Default, Ord, Eq, PartialOrd, CandidType, Deserialize, Serialize, +)] +pub struct TournamentMeta { + pub start_time: String, + pub end_time: String, + pub prize_pool: u64, + pub winning_prize: u64, + pub stream_url: Option, + pub description: String, + pub tournament_banner: Option, + pub tags: Vec, +} + +/// Status of a tournament +// #[derive(Debug, Serialize, Deserialize)] +// pub enum TournamentStatus { +// Upcoming, +// Ongoing, +// Completed, +// Cancelled, +// Archived, +// } + +/// Type of tournament funding +// #[derive(Debug, Serialize, Deserialize)] +// pub enum TournamentType { +// Prepaid, +// Crowdfunded, +// } + +/// Team size options +#[derive( + Clone, Debug, PartialEq, Default, Ord, Eq, PartialOrd, CandidType, Deserialize, Serialize, +)] +pub enum TeamType { + Duo, + Squad, + #[default] + Solo, +} + +/// Team model +#[derive( + Clone, Debug, PartialEq, Ord, Eq, PartialOrd, CandidType, Deserialize, Serialize, +)] +pub struct Team { + pub id: String, + pub name: String, + pub members: Vec, + pub captain: Principal, + pub created_at: String, + pub metadata: Option, +} + + + + + + + +/// Generic result type for Motoko-style unions +#[derive( + Clone, Debug, PartialEq, Ord, Eq, PartialOrd, CandidType, Deserialize, Serialize, +)] +pub enum OperationResult { + Ok(String), + Err(String), +} diff --git a/game_bloc_backend/src/tournaments/helper_functions.rs b/game_bloc_backend/src/tournaments/helper_functions.rs index 48224525..369994a0 100644 --- a/game_bloc_backend/src/tournaments/helper_functions.rs +++ b/game_bloc_backend/src/tournaments/helper_functions.rs @@ -1,4 +1,4 @@ -use crate::model::{GameType, Member, TournamentAccount, UserProfile}; +use crate::model::{GameType, Member, ParticipatingMember, TournamentAccount, UserProfile}; use crate::{ID_STORE, PROFILE_STORE, SQUAD_STORE}; use std::cmp::Ordering; @@ -47,6 +47,17 @@ pub fn append_squad_to_tournament( } let mut mutable_new_member_ign = new_member_ign.to_owned().unwrap(); ign.to_owned().append(&mut mutable_new_member_ign); + let mut squad_participating_member_list:Vec =vec![]; + for members in ign.to_owned() { + squad_participating_member_list.push(Member{ + name: members.0.to_string(), + principal_id: members.1.to_string(), + }) + } + squad.participating_members = ParticipatingMember{ + tournament_id: tournament.id_hash.clone(), + participating_squad_members:squad_participating_member_list, + }; } tournament.squad.push(squad); }); @@ -103,3 +114,116 @@ pub fn append_player_to_participants( } } } + +pub fn append_squad_to_tournament_v1( + squad_id: &String, + ign: Vec<(String, String, String)>, + new_member_ign: &Option>, + mut tournament: TournamentAccount, +) -> TournamentAccount { + match tournament + .to_owned() + .no_of_participants + .cmp(&(tournament.to_owned().user.len() as u128)) + { + Ordering::Greater => { + SQUAD_STORE.with(|squad_store| { + let mut squad = squad_store + .borrow() + .get(&squad_id.to_owned()) + .cloned() + .unwrap(); + if new_member_ign.is_some() { + let count = new_member_ign.to_owned().unwrap().len(); + if count > 0 { + PROFILE_STORE.with(|profile_store| { + loop { + if count == 0 { + break; + } + let mut user = profile_store + .borrow() + .get(&new_member_ign.to_owned().unwrap()[count - 1].0) + .cloned() + .unwrap(); + let missing: Member = Member { + name: user.to_owned().username, + principal_id: new_member_ign.to_owned().unwrap()[count - 1] + .0 + .to_owned(), + }; + squad.members.push(missing); + user.squad_badge = squad.id_hash.to_owned(); + profile_store.borrow_mut().insert( + new_member_ign.to_owned().unwrap()[count - 1].0.to_owned(), + user, + ); + } + squad_store + .borrow_mut() + .insert(squad_id.to_owned(), squad.to_owned()); + }); + } + let mut mutable_new_member_ign = new_member_ign.to_owned().unwrap(); + ign.to_owned().append(&mut mutable_new_member_ign); + } + tournament.squad.push(squad); + }); + match tournament.to_owned().squad_in_game_names { + None => { + tournament.squad_in_game_names = Some(vec![ign]); + tournament + } + Some(mut previous_igns) => { + previous_igns.push(ign); + tournament.squad_in_game_names = Some(previous_igns); + tournament + } + } + } + _ => tournament, + } +} + +pub fn append_player_to_participants_v1( + name: String, + ign: (String, String, String), + mut tournament: TournamentAccount, +) -> TournamentAccount { + match GameType::from_str(tournament.game_type.to_owned().as_str()) { + GameType::Single => { + match tournament + .to_owned() + .no_of_participants + .cmp(&(tournament.to_owned().user.len() as u128)) + { + Ordering::Greater => { + tournament.user.push(name.to_owned()); + match tournament.to_owned().in_game_names { + None => { + tournament.in_game_names = Some(vec![ign.to_owned()]); + } + Some(mut previous_igns) => { + previous_igns.push(ign); + tournament.in_game_names = Some(previous_igns); + } + } + let user_details = get_profile(name); + match tournament.user_details.to_owned() { + None => { + tournament.user_details = Some(vec![user_details]); + tournament + } + Some(mut previous_user_details) => { + previous_user_details.push(user_details); + tournament.user_details = Some(previous_user_details); + tournament + } + } + } + _ => tournament, + } + } + _ => tournament, + } +} diff --git a/icp_ledger.did b/interfaces/icp_ledger.did similarity index 100% rename from icp_ledger.did rename to interfaces/icp_ledger.did diff --git a/icrc_ledger.did b/interfaces/icrc_ledger.did similarity index 100% rename from icrc_ledger.did rename to interfaces/icrc_ledger.did diff --git a/ledger.did b/interfaces/ledger.did similarity index 100% rename from ledger.did rename to interfaces/ledger.did diff --git a/qhbym-qaaaa-aaaaa-aaafq-cai.did b/interfaces/qhbym-qaaaa-aaaaa-aaafq-cai.did similarity index 100% rename from qhbym-qaaaa-aaaaa-aaafq-cai.did rename to interfaces/qhbym-qaaaa-aaaaa-aaafq-cai.did diff --git a/ryjl3-tyaaa-aaaaa-aaaba-cai.did b/interfaces/ryjl3-tyaaa-aaaaa-aaaba-cai.did similarity index 100% rename from ryjl3-tyaaa-aaaaa-aaaba-cai.did rename to interfaces/ryjl3-tyaaa-aaaaa-aaaba-cai.did diff --git a/download_latest_icp_ledger.sh b/scripts/download_latest_icp_ledger.sh similarity index 100% rename from download_latest_icp_ledger.sh rename to scripts/download_latest_icp_ledger.sh diff --git a/install_didc.sh b/scripts/install_didc.sh similarity index 100% rename from install_didc.sh rename to scripts/install_didc.sh diff --git a/makefile b/scripts/makefile similarity index 100% rename from makefile rename to scripts/makefile diff --git a/point.sh b/scripts/point.sh similarity index 100% rename from point.sh rename to scripts/point.sh