From 760fa5f674f9e93b78b54d70d08091c52e1ae1cd Mon Sep 17 00:00:00 2001 From: loothero <100039621+loothero@users.noreply.github.com> Date: Sun, 18 Feb 2024 18:40:09 -0500 Subject: [PATCH] DevEx improvements (#547) (#548) * fixes failing tests in game entropy library * updates readme to be consistent with latest contract * updates repo to use starkli instead of legacy starknet * adds script to automate starkli account setup * adds script to automate contract deployment * adds DockerFile --- .devcontainer/Dockerfile | 21 ++++ .devcontainer/devcontainer.json | 10 +- .github/workflows/build.yml | 4 +- .gitignore | 1 + README.md | 115 +++++------------- contracts/game_entropy/src/game_entropy.cairo | 16 +-- scripts/deploy.sh | 14 ++- scripts/starkli_setup.sh | 64 ++++++++++ 8 files changed, 140 insertions(+), 105 deletions(-) create mode 100644 .devcontainer/Dockerfile create mode 100644 scripts/starkli_setup.sh diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile new file mode 100644 index 000000000..1399bcacf --- /dev/null +++ b/.devcontainer/Dockerfile @@ -0,0 +1,21 @@ +# Use Debian Bookworm as a base image +FROM debian:bookworm-slim + +# Avoid warnings by switching to noninteractive +ENV DEBIAN_FRONTEND=noninteractive + +# Update the package list and install minimal utilities +RUN apt-get update \ + && apt-get install -y --no-install-recommends \ + curl \ + git \ + ca-certificates \ + unzip \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* + +RUN curl --proto '=https' --tlsv1.2 -sSf https://docs.swmansion.com/scarb/install.sh | bash -s -- -v 2.5.4 +RUN curl https://get.starkli.sh | bash +RUN /root/.starkli/bin/starkliup +# Specify the command to run on container start +CMD ["bash"] \ No newline at end of file diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index f1bdc424f..bf19ad023 100755 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -1,10 +1,13 @@ { "name": "Rust", - "image": "mcr.microsoft.com/devcontainers/rust:0-1-bullseye", + "build": { + "dockerfile": "Dockerfile" + }, "customizations": { "vscode": { "extensions": [ - "starkware.cairo1" + "starkware.cairo1", + "github.copilot" ] } }, @@ -14,5 +17,6 @@ "CAIRO_COMPILER_DIR":"~/.cairo/target/release/", "CAIRO_COMPILER_ARGS":"--add-pythonic-hints" }, - "postCreateCommand":"curl --proto '=https' --tlsv1.2 -sSf https://docs.swmansion.com/scarb/install.sh | bash -s -- -v 0.7.0 && curl https://pyenv.run | bash && echo 'export PATH=\"$HOME/.pyenv/bin:$PATH\"' >> ~/.bashrc && echo 'eval \"$(pyenv init -)\"' >> ~/.bashrc && echo 'eval \"$(pyenv virtualenv-init -)\"' >> ~/.bashrc && $HOME/.pyenv/bin/pyenv install 3.9.0 && $HOME/.pyenv/bin/pyenv virtualenv 3.9.0 cairo_venv && echo 'pyenv activate cairo_venv' >> ~/.bashrc && echo 'pip install cairo-lang 2> /dev/null' >> ~/.bashrc" + "postCreateCommand": "git config --global core.editor \"code --wait\" && bash scripts/starkli_setup.sh", + "postStartCommand": "cd contracts && scarb build && scarb test" } \ No newline at end of file diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index b221b5770..d09d1c45d 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -22,8 +22,8 @@ jobs: market, obstacles, combat, - # game_entropy, - # game_snapshot, + game_entropy, + game_snapshot, ] steps: - uses: actions/checkout@v3 diff --git a/.gitignore b/.gitignore index 8771d4bfc..8e9ca9850 100644 --- a/.gitignore +++ b/.gitignore @@ -17,3 +17,4 @@ contracts/game_entropy/target/CACHEDIR.TAG contracts/game_entropy/target/dev/game_entropy.sierra scripts/stress_test.py +.env diff --git a/README.md b/README.md index f86b6d3a7..130a61a17 100644 --- a/README.md +++ b/README.md @@ -148,127 +148,70 @@ Loot Survivor is an onchain game, designed to be immutable and permanently hoste ### Deploying -#### Set up env - -Follow instructions here: `https://docs.starknet.io/documentation/getting_started/environment_setup/` - - -``` -source ~/cairo_venv/bin/activate -``` - -```bash -export STARKNET_NETWORK=alpha-goerli -export STARKNET_WALLET=starkware.starknet.wallets.open_zeppelin.OpenZeppelinAccount -export CAIRO_COMPILER_DIR=~/.cairo/target/release/ -export CAIRO_COMPILER_ARGS=--add-pythonic-hints - -# you will have an account from the Starknet ENV setup -export ACCOUNT_NAME=INSERT_YOUR_ACCOUNT_NAME_HERE -export ADVENTURER_ID=INSERT_YOUR_ADVENTURER_ID_HERE -export STRENGTH=0 -export DEXTERITY=1 -export VITALITY=2 -export INTELLIGENCE=4 -export CHARISMA=5 - -export LORDS_ADDRESS=0x059dac5df32cbce17b081399e97d90be5fba726f97f00638f838613d088e5a47 -export DAO_ADDRESS=0x020b96923a9e60f63a1829d440a03cf680768cadbc8fe737f71380258817d85b - -# nav to dir -cd contracts/game - -# build -scarb build - -# declare -starknet declare --contract target/dev/game_Game.sierra.json --account $ACCOUNT_NAME - -# deploy -# will be in the output of the previous command -starknet deploy --class_hash 0x2958304935054101c0aeab16cf6507adda1c98b4d977af40d59c2ae75f05767 --max_fee 100000000000000000 --input $LORDS_ADDRESS $DAO_ADDRESS --account $ACCOUNT_NAME -``` +#### Setup Starkli Account ```bash -# set contract address -export CONTRACT_ADDRESS=0x06ee32da9f22c736c4ef049719c0021380c302e5d449fbc8acf97489e16a9d05 +bash scripts/starkli_setup.sh ``` +#### Deploy Contract ```bash -starknet invoke --function mint --address $LORDS_ADDRESS --input 0x1feb9c05d31b70a1506decf52a809d57493bfcd5cc85d6a3e9fd54a12d64389 1000000000000000000000 0 --max_fee 10000000000000000 --account $ACCOUNT_NAME - -starknet invoke --function approve --address $LORDS_ADDRESS --input $CONTRACT_ADDRESS 1000000000000000000000 0 --max_fee 10000000000000000 --account $ACCOUNT_NAME +bash scripts/deploy.sh.sh ``` -### Game Actions +### Play -#### Start +#### Mint $lords and approve LS to spend ```bash -starknet invoke --function start --address $CONTRACT_ADDRESS --input 0x020b96923a9e60f63a1829d440a03cf680768cadbc8fe737f71380258817d85b 12 123 0 0 0 --max_fee 10000000000000000 --account $ACCOUNT_NAME +source "/workspaces/loot-survivor/.env" +starkli invoke $LORDS_ADDRESS mint 0x1feb9c05d31b70a1506decf52a809d57493bfcd5cc85d6a3e9fd54a12d64389 1000000000000000000000 0 --account $STARKNET_ACCOUNT --private-key $PRIVATE_KEY +starkli invoke $LORDS_ADDRESS approve $CONTRACT_ADDRESS 1000000000000000000000 0 --account $STARKNET_ACCOUNT --private-key $PRIVATE_KEY ``` -#### Explore +#### Start New Game ```bash -starknet invoke --function explore --address $CONTRACT_ADDRESS --input $ADVENTURER_ID 0 --max_fee 10000000000000000 --account $ACCOUNT_NAME +starkli invoke $CONTRACT_ADDRESS new_game 0x020b96923a9e60f63a1829d440a03cf680768cadbc8fe737f71380258817d85b 12 123 0 0 0 --account $STARKNET_ACCOUNT --private-key $PRIVATE_KEY ``` -#### Attack +#### Explore ```bash -starknet invoke --function attack --address $CONTRACT_ADDRESS --input $ADVENTURER_ID 0 --max_fee 10000000000000000 --account $ACCOUNT_NAME +starkli invoke $CONTRACT_ADDRESS explore $ADVENTURER_ID 0 --account $STARKNET_ACCOUNT --private-key $PRIVATE_KEY ``` -#### Flee +#### Attack Starter Beast ```bash -starknet invoke --function flee --address $CONTRACT_ADDRESS --input $ADVENTURER_ID 0 --max_fee 10000000000000000 --account $ACCOUNT_NAME +starkli invoke $CONTRACT_ADDRESS attack $ADVENTURER_ID 0 --account $STARKNET_ACCOUNT --private-key $PRIVATE_KEY ``` -#### Upgrade Stat (Charisma x 1) +#### Upgrade Adventurer ```bash -starknet invoke --function upgrade_stat --address $CONTRACT_ADDRESS --input $ADVENTURER_ID 0 $CHARISMA 1 --max_fee 10000000000000000 --account $ACCOUNT_NAME +starkli invoke $CONTRACT_ADDRESS upgrade $ADVENTURER_ID 0 $CHARISMA 1 --account $STARKNET_ACCOUNT --private-key $PRIVATE_KEY ``` -### Checking On Your Adventurer +### View Adventurer Details -##### Get full adventurer state +##### Adventurer State ```bash -starknet call --function get_adventurer --address $CONTRACT_ADDRESS --input $ADVENTURER_ID 0 --account $ACCOUNT_NAME +starkli call --watch $CONTRACT_ADDRESS get_adventurer $ADVENTURER_ID 0 --account $STARKNET_ACCOUNT --private-key $PRIVATE_KEY ``` -##### Get adventurer health +##### Get Adventurer Health ```bash -starknet call --function get_health --address $CONTRACT_ADDRESS --input $ADVENTURER_ID 0 --account $ACCOUNT_NAME +starkli call --watch $CONTRACT_ADDRESS get_health $ADVENTURER_ID 0 --account $STARKNET_ACCOUNT --private-key $PRIVATE_KEY ``` -##### Get adventurer gold +##### Get Adventurer Gold ```bash -starknet call --function get_gold --address $CONTRACT_ADDRESS --input $ADVENTURER_ID 0 --account $ACCOUNT_NAME +starkli call --watch $CONTRACT_ADDRESS get_gold $ADVENTURER_ID 0 --account $STARKNET_ACCOUNT --private-key $PRIVATE_KEY ``` -##### Get adventurer xp +##### Get Adventurer XP ```bash -starknet call --function get_xp --address $CONTRACT_ADDRESS --input $ADVENTURER_ID 0 --account $ACCOUNT_NAME +starkli call --watch $CONTRACT_ADDRESS get_xp $ADVENTURER_ID 0 --account $STARKNET_ACCOUNT --private-key $PRIVATE_KEY ``` -##### Get upgradable stat points +##### Get number of stat upgrades available ```bash -starknet call --function get_stat_upgrades_available --address $CONTRACT_ADDRESS --input $ADVENTURER_ID 0 --account $ACCOUNT_NAME -``` - -##### Get base charisma stat (doesn't include boost from items) -```bash -starknet call --function get_base_charisma --address $CONTRACT_ADDRESS --input $ADVENTURER_ID 0 --account $ACCOUNT_NAME -``` - -##### Get charisma stat including item boosts -```bash -starknet call --function get_charisma --address $CONTRACT_ADDRESS --input $ADVENTURER_ID 0 --account $ACCOUNT_NAME -``` - - -# Starkli Deploy - - -starkli declare /contracts/game/target/dev/game_Game.sierra.json --account ./account --keystore ./keys --max-fee 0.01 - -starkli deploy 0x00cccbd15bf27792e7635bd89da237de68b13d29ec01b5cae1da786b276be8a4 $LORDS_ADDRESS $DAO_ADDRESS 0x06fe9215a0f193431f30043e612d921b62331946529ebf5f258949a4b34aa799 --account ./account --keystore ./keys \ No newline at end of file +starkli call --watch $CONTRACT_ADDRESS get_stat_upgrades_available $ADVENTURER_ID 0 --account $STARKNET_ACCOUNT --private-key $PRIVATE_KEY +``` \ No newline at end of file diff --git a/contracts/game_entropy/src/game_entropy.cairo b/contracts/game_entropy/src/game_entropy.cairo index ccf0db6c8..4bdb3d630 100644 --- a/contracts/game_entropy/src/game_entropy.cairo +++ b/contracts/game_entropy/src/game_entropy.cairo @@ -87,7 +87,7 @@ impl ImplGameEntropy of IGameEntropy { block_number_diff * 3600 / block_timestamp_diff } - /// @notice Calculate the current rate of blocks produced per hour, based on a ten-minute window. + /// @notice Calculate the current rate of blocks produced per hour, based on a thirty minute window. /// @return The number of blocks produced per hour. #[inline(always)] fn current_blocks_per_hour(self: GameEntropy) -> u64 { @@ -179,17 +179,17 @@ mod tests { let hash = 0x123; let last_updated_block = 282360; let last_updated_time = 1696209920; - let next_update_block = 282364; + let next_update_block = 282380; let game_entropy = GameEntropy { hash, last_updated_block, last_updated_time, next_update_block, }; - let adventurer_idle_blocks = 3; + let adventurer_idle_blocks = 4; let is_idle = game_entropy.is_adventurer_idle(adventurer_idle_blocks); assert(!is_idle, 'should not be idle'); - let adventurer_idle_blocks = 4; + let adventurer_idle_blocks = 6; let is_idle = game_entropy.is_adventurer_idle(adventurer_idle_blocks); assert(is_idle, 'should be idle'); } @@ -208,7 +208,7 @@ mod tests { // next entropy rotation is in 3 blocks which is 10 minutes // at 1 block per 3mins (20 blocks per hour) - assert(next_entropy_rotation == 4, 'wrong rotation, slow speed'); + assert(next_entropy_rotation == 11, 'wrong rotation, slow speed'); // starknet expects to eventually be producing blocks every 30s (2 per min, 120 per hour) let blocks_per_hour = 120; @@ -216,7 +216,7 @@ mod tests { current_block, blocks_per_hour ); // after this blockspeed, ten minutes is now 20 blocks in the future - assert(next_entropy_rotation == 21, 'wrong rotation, fast speed'); + assert(next_entropy_rotation == 61, 'wrong rotation, fast speed'); } #[test] @@ -229,9 +229,9 @@ mod tests { next_update_block: 282481, }; let blocks_per_hour = game_entropy.current_blocks_per_hour(); - assert(blocks_per_hour == 96, 'wrong blocks per hour') + assert(blocks_per_hour == 32, 'wrong blocks per hour') } - + #[test] #[available_gas(29280)] fn test_calculate_blocks_per_hour() { diff --git a/scripts/deploy.sh b/scripts/deploy.sh index 3bbc6d5d8..d2a685270 100644 --- a/scripts/deploy.sh +++ b/scripts/deploy.sh @@ -1,10 +1,12 @@ #!/bin/bash -export STARKNET_NETWORK=alpha-goerli -export STARKNET_WALLET=starkware.starknet.wallets.open_zeppelin.OpenZeppelinAccount -export CAIRO_COMPILER_DIR=~/.cairo/target/release/ -export CAIRO_COMPILER_ARGS=--add-pythonic-hints +# Source env vars +ENV_FILE="/workspaces/loot-survivor/.env" +source $ENV_FILE -scarb contracts/game/build +# build game contract +cd /workspaces/loot-survivor/contracts/ +scarb build -starknet declare --contract contracts/game/target/dev/game_Game.sierra.json --account deployer_4 +# declare game contract +starkli declare --watch /workspaces/loot-survivor/target/dev/game_Game.contract_class.json --account $STARKNET_ACCOUNT --private-key $PRIVATE_KEY \ No newline at end of file diff --git a/scripts/starkli_setup.sh b/scripts/starkli_setup.sh new file mode 100644 index 000000000..84eefddb3 --- /dev/null +++ b/scripts/starkli_setup.sh @@ -0,0 +1,64 @@ +ENV_FILE="/workspaces/loot-survivor/.env" + +# If there is already an account in .env, skip that +if grep -q "^ACCOUNT_ADDRESS=" "$ENV_FILE"; then + echo "Account already setup, exiting" + exit +fi + +echo "LORDS_ADDRESS=0x059dac5df32cbce17b081399e97d90be5fba726f97f00638f838613d088e5a47" > $ENV_FILE +echo "DAO_ADDRESS=0x059dac5df32cbce17b081399e97d90be5fba726f97f00638f838613d088e5a47" >> $ENV_FILE + +# these are mainnet contracts. If you are running on testnet, please update these to right contracts +echo "GOLDEN_TOKEN_ADDRESS=0x04f5e296c805126637552cf3930e857f380e7c078e8f00696de4fc8545356b1d" >> $ENV_FILE +echo "BEASTS_ADDRESS=0x0158160018d590d93528995b340260e65aedd76d28a686e9daa5c4e8fad0c5dd" >> $ENV_FILE + +echo "ADVENTURER_ID=1" >> $ENV_FILE + +echo "STRENGTH=0" >> $ENV_FILE +echo "DEXTERITY=1" >> $ENV_FILE +echo "VITALITY=2" >> $ENV_FILE +echo "WISDOM=3" >> $ENV_FILE +echo "INTELLIGENCE=4" >> $ENV_FILE +echo "CHARISMA=5" >> $ENV_FILE + + +# initialize starknet directories +mkdir -p $HOME/.starknet +STARKNET_ACCOUNT=$HOME/.starknet/account +STARKNET_KEYSTORE=$HOME/.starknet/keystore + +# Change directory to starkli +cd /root/.starkli/bin/ + +# Generate keypair +output=$(./starkli signer gen-keypair) + +# Store keys as vars so we can use them and later write to .bashrc +private_key=$(echo "$output" | awk '/Private key/ {print $4}') +public_key=$(echo "$output" | awk '/Public key/ {print $4}') + +# Initialize OZ account and save output +account_output=$(./starkli account oz init $STARKNET_ACCOUNT --private-key $private_key 2>&1) +account_address=$(echo "$account_output" | grep -oE '0x[0-9a-fA-F]+') + +# Deploy Account +./starkli account deploy $STARKNET_ACCOUNT --private-key $private_key + +# Output key and account info +echo "Private Key: $private_key" +echo "Public Key: $public_key" +echo "Account: $account_address" + +# Add keys and account to .bashrc as env vars for easy access in shell +echo "PRIVATE_KEY=\"$private_key\"" >> $ENV_FILE +echo "PUBLIC_KEY=\"$public_key\"" >> $ENV_FILE +echo "ACCOUNT_ADDRESS=\"$account_address\"" >> $ENV_FILE +echo "STARKNET_ACCOUNT=$STARKNET_ACCOUNT" >> $ENV_FILE +echo "STARKNET_KEYSTORE=$STARKNET_KEYSTORE" >> $ENV_FILE + +echo "set -o allexport" >> ~/.bashrc +echo "source $ENV_FILE" >> ~/.bashrc +echo "set +o allexport" >> ~/.bashrc + +source ~/.bashrc \ No newline at end of file