From 5c22c6c271a6e2ddee2917b8d398f3752ea393ed Mon Sep 17 00:00:00 2001 From: Brandon Roberts Date: Thu, 11 Apr 2024 11:08:27 -0500 Subject: [PATCH] Add calldata to quests to allow easier implementation of generic quests --- onchain/src/art_peace.cairo | 12 ++++++------ onchain/src/interface.cairo | 6 +++--- onchain/src/quests/interface.cairo | 5 +++-- onchain/src/quests/pixel_quest.cairo | 9 ++++----- onchain/src/tests/art_peace.cairo | 22 ++++++++++++---------- postgres/init.sql | 1 + 6 files changed, 29 insertions(+), 26 deletions(-) diff --git a/onchain/src/art_peace.cairo b/onchain/src/art_peace.cairo index 288604f8..0652e247 100644 --- a/onchain/src/art_peace.cairo +++ b/onchain/src/art_peace.cairo @@ -319,13 +319,13 @@ pub mod ArtPeace { quests.span() } - fn claim_daily_quest(ref self: ContractState, day_index: u32, quest_id: u32) { + fn claim_daily_quest(ref self: ContractState, day_index: u32, quest_id: u32, calldata: Span) { let now = starknet::get_block_timestamp(); assert!(now <= self.end_time.read()); // TODO: Only allow to claim the quest of the current day let quest = self.daily_quests.read((day_index, quest_id)); let user = starknet::get_caller_address(); - let reward = IQuestDispatcher { contract_address: quest }.claim(user); + let reward = IQuestDispatcher { contract_address: quest }.claim(user, calldata); if reward > 0 { self .extra_pixels @@ -336,12 +336,12 @@ pub mod ArtPeace { } } - fn claim_today_quest(ref self: ContractState, quest_id: u32) { + fn claim_today_quest(ref self: ContractState, quest_id: u32, calldata: Span) { let now = starknet::get_block_timestamp(); assert!(now <= self.end_time.read()); let quest = self.daily_quests.read((self.day_index.read(), quest_id)); let user = starknet::get_caller_address(); - let reward = IQuestDispatcher { contract_address: quest }.claim(user); + let reward = IQuestDispatcher { contract_address: quest }.claim(user, calldata); if reward > 0 { self .extra_pixels @@ -352,12 +352,12 @@ pub mod ArtPeace { } } - fn claim_main_quest(ref self: ContractState, quest_id: u32) { + fn claim_main_quest(ref self: ContractState, quest_id: u32, calldata: Span) { let now = starknet::get_block_timestamp(); assert!(now <= self.end_time.read()); let quest = self.main_quests.read(quest_id); let user = starknet::get_caller_address(); - let reward = IQuestDispatcher { contract_address: quest }.claim(user); + let reward = IQuestDispatcher { contract_address: quest }.claim(user, calldata); if reward > 0 { self .extra_pixels diff --git a/onchain/src/interface.cairo b/onchain/src/interface.cairo index 9882ff36..07a23431 100644 --- a/onchain/src/interface.cairo +++ b/onchain/src/interface.cairo @@ -56,9 +56,9 @@ pub trait IArtPeace { fn get_main_quests(self: @TContractState) -> Span; // Claim quests - fn claim_daily_quest(ref self: TContractState, day_index: u32, quest_id: u32); - fn claim_today_quest(ref self: TContractState, quest_id: u32); - fn claim_main_quest(ref self: TContractState, quest_id: u32); + fn claim_daily_quest(ref self: TContractState, day_index: u32, quest_id: u32, calldata: Span); + fn claim_today_quest(ref self: TContractState, quest_id: u32, calldata: Span); + fn claim_main_quest(ref self: TContractState, quest_id: u32, calldata: Span); // Stats fn get_user_pixels_placed(self: @TContractState, user: starknet::ContractAddress) -> u32; diff --git a/onchain/src/quests/interface.cairo b/onchain/src/quests/interface.cairo index 2b0b6862..41b5f21f 100644 --- a/onchain/src/quests/interface.cairo +++ b/onchain/src/quests/interface.cairo @@ -4,6 +4,7 @@ use starknet::ContractAddress; pub struct QuestClaimed { pub user: ContractAddress, pub reward: u32, + pub calldata: Span, } #[starknet::interface] @@ -11,7 +12,7 @@ pub trait IQuest { // Return the reward for the quest. fn get_reward(self: @TContractState) -> u32; // Return if the user can claim the quest. - fn is_claimable(self: @TContractState, user: ContractAddress) -> bool; + fn is_claimable(self: @TContractState, user: ContractAddress, calldata: Span) -> bool; // Claim the quest. - fn claim(ref self: TContractState, user: ContractAddress) -> u32; + fn claim(ref self: TContractState, user: ContractAddress, calldata: Span) -> u32; } diff --git a/onchain/src/quests/pixel_quest.cairo b/onchain/src/quests/pixel_quest.cairo index efddc53e..71fb4e51 100644 --- a/onchain/src/quests/pixel_quest.cairo +++ b/onchain/src/quests/pixel_quest.cairo @@ -65,14 +65,13 @@ mod PixelQuest { } } - // TODO: Test all #[abi(embed_v0)] impl PixelQuest of IQuest { fn get_reward(self: @ContractState) -> u32 { return self.reward.read(); } - fn is_claimable(self: @ContractState, user: ContractAddress) -> bool { + fn is_claimable(self: @ContractState, user: ContractAddress, calldata: Span) -> bool { let art_peace = self.art_peace.read(); if self.claimed.read(user) { return false; @@ -92,18 +91,18 @@ mod PixelQuest { } } - fn claim(ref self: ContractState, user: ContractAddress) -> u32 { + fn claim(ref self: ContractState, user: ContractAddress, calldata: Span) -> u32 { assert( get_caller_address() == self.art_peace.read().contract_address, 'Only ArtPeace can claim quests' ); - if !self.is_claimable(user) { + if !self.is_claimable(user, calldata) { return 0; } self.claimed.write(user, true); let reward = self.reward.read(); - self.emit(QuestClaimed { user: user, reward: reward }); + self.emit(QuestClaimed { user, reward, calldata }); return reward; } } diff --git a/onchain/src/tests/art_peace.cairo b/onchain/src/tests/art_peace.cairo index eff84e67..c0619416 100644 --- a/onchain/src/tests/art_peace.cairo +++ b/onchain/src/tests/art_peace.cairo @@ -21,6 +21,10 @@ fn ART_PEACE_CONTRACT() -> ContractAddress { contract_address_const::<'ArtPeace'>() } +fn EMPTY_CALLDATA() -> Span { + array![].span() +} + fn deploy_contract() -> ContractAddress { let contract = snf::declare("ArtPeace"); let mut calldata = array![]; @@ -194,8 +198,8 @@ fn pixel_quest_test() { let pos = x + y * WIDTH; let color = 0x5; art_peace.place_pixel(pos, color); - art_peace.claim_daily_quest(0, 0); - art_peace.claim_main_quest(0); + art_peace.claim_daily_quest(0, 0, EMPTY_CALLDATA()); + art_peace.claim_main_quest(0, EMPTY_CALLDATA()); assert!(art_peace.get_extra_pixels_count() == 0, "Extra pixels are wrong after invalid claims"); warp_to_next_available_time(art_peace); @@ -203,8 +207,8 @@ fn pixel_quest_test() { let y = 25; let color = 0x7; art_peace.place_pixel_xy(x, y, color); - art_peace.claim_daily_quest(0, 0); - art_peace.claim_main_quest(0); + art_peace.claim_daily_quest(0, 0, EMPTY_CALLDATA()); + art_peace.claim_main_quest(0, EMPTY_CALLDATA()); assert!(art_peace.get_extra_pixels_count() == 0, "Extra pixels are wrong after invalid claims"); warp_to_next_available_time(art_peace); @@ -213,8 +217,8 @@ fn pixel_quest_test() { let pos = x + y * WIDTH; let color = 0x9; art_peace.place_pixel(pos, color); - art_peace.claim_daily_quest(0, 0); - art_peace.claim_main_quest(0); + art_peace.claim_daily_quest(0, 0, EMPTY_CALLDATA()); + art_peace.claim_main_quest(0, EMPTY_CALLDATA()); assert!( art_peace.get_extra_pixels_count() == 10, "Extra pixels are wrong after daily quest claim" ); @@ -224,8 +228,8 @@ fn pixel_quest_test() { let y = 35; let color = 0xB; art_peace.place_pixel_xy(x, y, color); - art_peace.claim_daily_quest(0, 0); - art_peace.claim_main_quest(0); + art_peace.claim_daily_quest(0, 0, EMPTY_CALLDATA()); + art_peace.claim_main_quest(0, EMPTY_CALLDATA()); assert!( art_peace.get_extra_pixels_count() == 30, "Extra pixels are wrong after main quest claim" ); @@ -339,5 +343,3 @@ fn increase_day_panic_test() { art_peace.increase_day_index(); } // TODO: test invalid template inputs - - diff --git a/postgres/init.sql b/postgres/init.sql index 920ab513..369ec13d 100644 --- a/postgres/init.sql +++ b/postgres/init.sql @@ -52,6 +52,7 @@ CREATE TABLE Quests ( ); CREATE INDEX quests_dayIndex_index ON Quests (dayIndex); +-- TODO: Add calldata field CREATE TABLE UserQuests ( key integer NOT NULL PRIMARY KEY, userAddress char(64) NOT NULL,