diff --git a/.github/workflows/demo.yaml b/.github/workflows/demo.yaml deleted file mode 100644 index 98f41b2c0..000000000 --- a/.github/workflows/demo.yaml +++ /dev/null @@ -1,64 +0,0 @@ -name: scaffold-stark-demo workflow - -on: - pull_request: - types: [closed] - branches: [main] - paths: - - 'packages/nextjs/**' - -jobs: - version-bump-nextjs: - runs-on: ubuntu-22.04 - steps: - - - name: Checkout Source Repository - uses: actions/checkout@v4 - with: - repository: Quantum3-Labs/scaffold-stark-2 - token: ${{ secrets.ORG_GITHUB_TOKEN }} - path: source_repo - - - name: Modify scaffoldConfig in Source Repository - run: | - cd source_repo - sed -i 's/targetNetworks: \[chains.devnet\]/targetNetworks: \[chains.sepolia\]/' packages/nextjs/scaffold.config.ts - cat packages/nextjs/scaffold.config.ts - - - name: Set up Node.js - uses: actions/setup-node@v3 - with: - node-version: 20 - registry-url: 'https://registry.yarnpkg.com' - - - name: Deploy to vercel - if: success() - id: deploy - env: - VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }} - VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID }} - VERCEL_TOKEN: ${{ secrets.VERCEL_TOKEN }} - run: | - cd source_repo - yarn install - vercel link --yes --project $VERCEL_PROJECT_ID --token $VERCEL_TOKEN --scope $VERCEL_ORG_ID - vercel --build-env NEXT_PUBLIC_IGNORE_BUILD_ERROR=true --prod --token $VERCEL_TOKEN --scope $VERCEL_ORG_ID - - - name: Notify Slack on Success - if: success() - uses: slackapi/slack-github-action@v1.26.0 - with: - channel-id: ${{ secrets.SLACK_CHANNEL_ID }} - slack-message: "GitHub deployed to vercel result: ${{ job.status }}\nRepository Name: ${{ github.repository }}\n${{ github.event.pull_request.html_url || github.event.head_commit.url }}" - env: - SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }} - - - name: Notify Slack on Failure - if: failure() - uses: slackapi/slack-github-action@v1.26.0 - with: - channel-id: ${{ secrets.SLACK_CHANNEL_ID }} - slack-message: "GitHub deployed to vercel result: ${{ job.status }}\nRepository Name: ${{ github.repository }}\n${{ github.event.pull_request.html_url || github.event.head_commit.url }}" - env: - SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }} - diff --git a/.github/workflows/release-create-stark.yaml b/.github/workflows/release-create-stark.yaml deleted file mode 100644 index 47c698ccf..000000000 --- a/.github/workflows/release-create-stark.yaml +++ /dev/null @@ -1,114 +0,0 @@ -name: Version Bump and Notify - -on: - pull_request: - types: [closed] - branches: [main] - -jobs: - version-bump: - runs-on: ubuntu-22.04 - - steps: - - name: Checkout Source Repository - uses: actions/checkout@v4 - with: - repository: Quantum3-Labs/scaffold-stark-2 - token: ${{ secrets.ORG_GITHUB_TOKEN }} - path: source_repo - - - name: Checkout Destination Repository - uses: actions/checkout@v4 - with: - repository: Quantum3-Labs/create-stark - token: ${{ secrets.ORG_GITHUB_TOKEN }} - path: destination_repo - - - name: Determine version bump type - id: version - run: | - cd source_repo - commit_message=$(git log -1 --pretty=%B) - if [[ "$commit_message" == *"[major]"* ]]; then - echo "type=major" >> "$GITHUB_ENV" - elif [[ "$commit_message" == *"[minor]"* ]]; then - echo "type=minor" >> "$GITHUB_ENV" - else - echo "type=patch" >> "$GITHUB_ENV" - fi - - - name: Bump version in Source Repository - id: bump-version-source - run: | - cd source_repo - git config --global user.name 'github-actions[bot]' - git config --global user.email 'github-actions[bot]@users.noreply.github.com' - new_version=$(npm version ${{ env.type }} -m "chore(release): %s [skip ci]") - echo "NEW_VERSION=${new_version}" >> "$GITHUB_ENV" - git push origin main --follow-tags - - - name: Copy Files to Destination Repository - run: | - rsync -av --delete --exclude='.git' source_repo/ destination_repo/templates/base - cd destination_repo - git add . - git commit -m "chore: sync files from scaffold-stark-2 [skip ci]" - - - name: Format .gitignore files - run: | - find destination_repo/templates/base -type f -name ".gitignore" | while read -r gitignore_file; do - mjs_file="${gitignore_file%/*}/.gitignore.template.mjs" - gitignore_content=$(cat "$gitignore_file") - cat > "$mjs_file" <<-EOF - const contents = () => - \`${gitignore_content}\` - - export default contents; - EOF - rm "$gitignore_file" - done - cd destination_repo - git add . - git commit -m "Processed $gitignore_file into $mjs_file" - - - name: Bump version in Destination Repository - id: bump-version-destination - run: | - cd destination_repo - git config --global user.name 'github-actions[bot]' - git config --global user.email 'github-actions[bot]@users.noreply.github.com' - new_version=$(npm version ${{ env.type }} -m "chore(release): %s [skip ci]") - git push origin main --follow-tags - - - name: Set up Node.js - uses: actions/setup-node@v3 - with: - node-version: '16' - registry-url: 'https://registry.npmjs.org/' - - - name: Publish release - if: success() - id: publish-release - run: | - cd destination_repo - npm install && npm run build && npm publish - env: - NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} - - - name: Notify Slack on Success - if: success() - uses: slackapi/slack-github-action@v1.26.0 - with: - channel-id: ${{ secrets.SLACK_CHANNEL_ID }} - slack-message: "GitHub Action succeeded for version bump to ${{ env.NEW_VERSION }}." - env: - SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }} - - - name: Notify Slack on Failure - if: failure() - uses: slackapi/slack-github-action@v1.26.0 - with: - channel-id: ${{ secrets.SLACK_CHANNEL_ID }} - slack-message: "GitHub Action failed for version bump." - env: - SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }} diff --git a/packages/nextjs/contracts/deployedContracts.ts b/packages/nextjs/contracts/deployedContracts.ts index 25751cee0..b96d078d1 100644 --- a/packages/nextjs/contracts/deployedContracts.ts +++ b/packages/nextjs/contracts/deployedContracts.ts @@ -3,6 +3,642 @@ * You should not edit it manually or your changes might be overwritten. */ -const deployedContracts = {} as const; +const deployedContracts = { + devnet: { + DiceGame: { + address: + "0x56532915f8755d81641ef7da74e358d88ac31ba40bce0c2a53ddef7a6c8dedd", + abi: [ + { + type: "impl", + name: "DiceGameImpl", + interface_name: "contracts::DiceGame::IDiceGame", + }, + { + type: "struct", + name: "core::integer::u256", + members: [ + { + name: "low", + type: "core::integer::u128", + }, + { + name: "high", + type: "core::integer::u128", + }, + ], + }, + { + type: "struct", + name: "openzeppelin::token::erc20::interface::IERC20CamelDispatcher", + members: [ + { + name: "contract_address", + type: "core::starknet::contract_address::ContractAddress", + }, + ], + }, + { + type: "interface", + name: "contracts::DiceGame::IDiceGame", + items: [ + { + type: "function", + name: "roll_dice", + inputs: [ + { + name: "amount", + type: "core::integer::u256", + }, + ], + outputs: [], + state_mutability: "external", + }, + { + type: "function", + name: "last_dice_value", + inputs: [], + outputs: [ + { + type: "core::integer::u256", + }, + ], + state_mutability: "view", + }, + { + type: "function", + name: "nonce", + inputs: [], + outputs: [ + { + type: "core::integer::u256", + }, + ], + state_mutability: "view", + }, + { + type: "function", + name: "prize", + inputs: [], + outputs: [ + { + type: "core::integer::u256", + }, + ], + state_mutability: "view", + }, + { + type: "function", + name: "eth_token", + inputs: [], + outputs: [ + { + type: "openzeppelin::token::erc20::interface::IERC20CamelDispatcher", + }, + ], + state_mutability: "view", + }, + ], + }, + { + type: "constructor", + name: "constructor", + inputs: [ + { + name: "eth_token_address", + type: "core::starknet::contract_address::ContractAddress", + }, + ], + }, + { + type: "event", + name: "contracts::DiceGame::DiceGame::Roll", + kind: "struct", + members: [ + { + name: "player", + type: "core::starknet::contract_address::ContractAddress", + kind: "key", + }, + { + name: "amount", + type: "core::integer::u256", + kind: "data", + }, + { + name: "roll", + type: "core::integer::u256", + kind: "data", + }, + ], + }, + { + type: "event", + name: "contracts::DiceGame::DiceGame::Winner", + kind: "struct", + members: [ + { + name: "winner", + type: "core::starknet::contract_address::ContractAddress", + kind: "data", + }, + { + name: "amount", + type: "core::integer::u256", + kind: "data", + }, + ], + }, + { + type: "event", + name: "contracts::DiceGame::DiceGame::Event", + kind: "enum", + variants: [ + { + name: "Roll", + type: "contracts::DiceGame::DiceGame::Roll", + kind: "nested", + }, + { + name: "Winner", + type: "contracts::DiceGame::DiceGame::Winner", + kind: "nested", + }, + ], + }, + ], + classHash: + "0x30c5a46ac42247a384b77d044a851fb5f284c853043d014b19cf29eeaed03f8", + }, + RiggedRoll: { + address: + "0x59d7a0a3a619fcecedc8122ff6b9e08cf2a689afc61b84c7939576361c09276", + abi: [ + { + type: "impl", + name: "RiggedRollImpl", + interface_name: "contracts::RiggedRoll::IRiggedRoll", + }, + { + type: "struct", + name: "core::integer::u256", + members: [ + { + name: "low", + type: "core::integer::u128", + }, + { + name: "high", + type: "core::integer::u128", + }, + ], + }, + { + type: "interface", + name: "contracts::RiggedRoll::IRiggedRoll", + items: [ + { + type: "function", + name: "rigged_roll", + inputs: [ + { + name: "amount", + type: "core::integer::u256", + }, + ], + outputs: [], + state_mutability: "external", + }, + { + type: "function", + name: "withdraw", + inputs: [ + { + name: "to", + type: "core::starknet::contract_address::ContractAddress", + }, + { + name: "amount", + type: "core::integer::u256", + }, + ], + outputs: [], + state_mutability: "external", + }, + { + type: "function", + name: "last_dice_value", + inputs: [], + outputs: [ + { + type: "core::integer::u256", + }, + ], + state_mutability: "view", + }, + { + type: "function", + name: "predicted_roll", + inputs: [], + outputs: [ + { + type: "core::integer::u256", + }, + ], + state_mutability: "view", + }, + { + type: "function", + name: "dice_game", + inputs: [], + outputs: [ + { + type: "core::starknet::contract_address::ContractAddress", + }, + ], + state_mutability: "view", + }, + ], + }, + { + type: "impl", + name: "OwnableImpl", + interface_name: "openzeppelin::access::ownable::interface::IOwnable", + }, + { + type: "interface", + name: "openzeppelin::access::ownable::interface::IOwnable", + items: [ + { + type: "function", + name: "owner", + inputs: [], + outputs: [ + { + type: "core::starknet::contract_address::ContractAddress", + }, + ], + state_mutability: "view", + }, + { + type: "function", + name: "transfer_ownership", + inputs: [ + { + name: "new_owner", + type: "core::starknet::contract_address::ContractAddress", + }, + ], + outputs: [], + state_mutability: "external", + }, + { + type: "function", + name: "renounce_ownership", + inputs: [], + outputs: [], + state_mutability: "external", + }, + ], + }, + { + type: "constructor", + name: "constructor", + inputs: [ + { + name: "dice_game_address", + type: "core::starknet::contract_address::ContractAddress", + }, + { + name: "owner", + type: "core::starknet::contract_address::ContractAddress", + }, + ], + }, + { + type: "event", + name: "openzeppelin::access::ownable::ownable::OwnableComponent::OwnershipTransferred", + kind: "struct", + members: [ + { + name: "previous_owner", + type: "core::starknet::contract_address::ContractAddress", + kind: "key", + }, + { + name: "new_owner", + type: "core::starknet::contract_address::ContractAddress", + kind: "key", + }, + ], + }, + { + type: "event", + name: "openzeppelin::access::ownable::ownable::OwnableComponent::OwnershipTransferStarted", + kind: "struct", + members: [ + { + name: "previous_owner", + type: "core::starknet::contract_address::ContractAddress", + kind: "key", + }, + { + name: "new_owner", + type: "core::starknet::contract_address::ContractAddress", + kind: "key", + }, + ], + }, + { + type: "event", + name: "openzeppelin::access::ownable::ownable::OwnableComponent::Event", + kind: "enum", + variants: [ + { + name: "OwnershipTransferred", + type: "openzeppelin::access::ownable::ownable::OwnableComponent::OwnershipTransferred", + kind: "nested", + }, + { + name: "OwnershipTransferStarted", + type: "openzeppelin::access::ownable::ownable::OwnableComponent::OwnershipTransferStarted", + kind: "nested", + }, + ], + }, + { + type: "event", + name: "contracts::RiggedRoll::RiggedRoll::Event", + kind: "enum", + variants: [ + { + name: "OwnableEvent", + type: "openzeppelin::access::ownable::ownable::OwnableComponent::Event", + kind: "flat", + }, + ], + }, + ], + classHash: + "0xce37e709ce13262a7803866491fb40eb7b1d8275d915c188a1aaa32172c8f9", + }, + YourContract: { + address: + "0x8314df9b968d40c10cadc6e8bdcdb71f8b0d14e159a776709de6b4898fce5b", + abi: [ + { + type: "impl", + name: "YourContractImpl", + interface_name: "contracts::YourContract::IYourContract", + }, + { + type: "struct", + name: "core::byte_array::ByteArray", + members: [ + { + name: "data", + type: "core::array::Array::", + }, + { + name: "pending_word", + type: "core::felt252", + }, + { + name: "pending_word_len", + type: "core::integer::u32", + }, + ], + }, + { + type: "struct", + name: "core::integer::u256", + members: [ + { + name: "low", + type: "core::integer::u128", + }, + { + name: "high", + type: "core::integer::u128", + }, + ], + }, + { + type: "enum", + name: "core::bool", + variants: [ + { + name: "False", + type: "()", + }, + { + name: "True", + type: "()", + }, + ], + }, + { + type: "interface", + name: "contracts::YourContract::IYourContract", + items: [ + { + type: "function", + name: "gretting", + inputs: [], + outputs: [ + { + type: "core::byte_array::ByteArray", + }, + ], + state_mutability: "view", + }, + { + type: "function", + name: "set_gretting", + inputs: [ + { + name: "new_greeting", + type: "core::byte_array::ByteArray", + }, + { + name: "amount_eth", + type: "core::integer::u256", + }, + ], + outputs: [], + state_mutability: "external", + }, + { + type: "function", + name: "withdraw", + inputs: [], + outputs: [], + state_mutability: "external", + }, + { + type: "function", + name: "premium", + inputs: [], + outputs: [ + { + type: "core::bool", + }, + ], + state_mutability: "view", + }, + ], + }, + { + type: "impl", + name: "OwnableImpl", + interface_name: "openzeppelin::access::ownable::interface::IOwnable", + }, + { + type: "interface", + name: "openzeppelin::access::ownable::interface::IOwnable", + items: [ + { + type: "function", + name: "owner", + inputs: [], + outputs: [ + { + type: "core::starknet::contract_address::ContractAddress", + }, + ], + state_mutability: "view", + }, + { + type: "function", + name: "transfer_ownership", + inputs: [ + { + name: "new_owner", + type: "core::starknet::contract_address::ContractAddress", + }, + ], + outputs: [], + state_mutability: "external", + }, + { + type: "function", + name: "renounce_ownership", + inputs: [], + outputs: [], + state_mutability: "external", + }, + ], + }, + { + type: "constructor", + name: "constructor", + inputs: [ + { + name: "owner", + type: "core::starknet::contract_address::ContractAddress", + }, + ], + }, + { + type: "event", + name: "openzeppelin::access::ownable::ownable::OwnableComponent::OwnershipTransferred", + kind: "struct", + members: [ + { + name: "previous_owner", + type: "core::starknet::contract_address::ContractAddress", + kind: "key", + }, + { + name: "new_owner", + type: "core::starknet::contract_address::ContractAddress", + kind: "key", + }, + ], + }, + { + type: "event", + name: "openzeppelin::access::ownable::ownable::OwnableComponent::OwnershipTransferStarted", + kind: "struct", + members: [ + { + name: "previous_owner", + type: "core::starknet::contract_address::ContractAddress", + kind: "key", + }, + { + name: "new_owner", + type: "core::starknet::contract_address::ContractAddress", + kind: "key", + }, + ], + }, + { + type: "event", + name: "openzeppelin::access::ownable::ownable::OwnableComponent::Event", + kind: "enum", + variants: [ + { + name: "OwnershipTransferred", + type: "openzeppelin::access::ownable::ownable::OwnableComponent::OwnershipTransferred", + kind: "nested", + }, + { + name: "OwnershipTransferStarted", + type: "openzeppelin::access::ownable::ownable::OwnableComponent::OwnershipTransferStarted", + kind: "nested", + }, + ], + }, + { + type: "event", + name: "contracts::YourContract::YourContract::GreetingChanged", + kind: "struct", + members: [ + { + name: "greeting_setter", + type: "core::starknet::contract_address::ContractAddress", + kind: "key", + }, + { + name: "new_greeting", + type: "core::byte_array::ByteArray", + kind: "key", + }, + { + name: "premium", + type: "core::bool", + kind: "data", + }, + { + name: "value", + type: "core::integer::u256", + kind: "data", + }, + ], + }, + { + type: "event", + name: "contracts::YourContract::YourContract::Event", + kind: "enum", + variants: [ + { + name: "OwnableEvent", + type: "openzeppelin::access::ownable::ownable::OwnableComponent::Event", + kind: "flat", + }, + { + name: "GreetingChanged", + type: "contracts::YourContract::YourContract::GreetingChanged", + kind: "nested", + }, + ], + }, + ], + classHash: + "0x63f027df0f2faa7a7dd3ff7ddd301ac67dfe18f947aad36b490ac4fac788b73", + }, + }, +} as const; export default deployedContracts; diff --git a/packages/snfoundry/contracts/src/YourContract.cairo b/packages/snfoundry/contracts/src/YourContract.cairo new file mode 100644 index 000000000..827cb713d --- /dev/null +++ b/packages/snfoundry/contracts/src/YourContract.cairo @@ -0,0 +1,103 @@ +#[starknet::interface] +pub trait IYourContract { + fn gretting(self: @TContractState) -> ByteArray; + fn set_gretting(ref self: TContractState, new_greeting: ByteArray, amount_eth: u256); + fn withdraw(ref self: TContractState); + fn premium(self: @TContractState) -> bool; +} + +#[starknet::contract] +mod YourContract { + use openzeppelin::access::ownable::OwnableComponent; + use openzeppelin::token::erc20::interface::{IERC20CamelDispatcher, IERC20CamelDispatcherTrait}; + use starknet::{get_caller_address, get_contract_address}; + use super::{IYourContract}; + use starknet::{ContractAddress, contract_address_const}; + + component!(path: OwnableComponent, storage: ownable, event: OwnableEvent); + + #[abi(embed_v0)] + impl OwnableImpl = OwnableComponent::OwnableImpl; + impl OwnableInternalImpl = OwnableComponent::InternalImpl; + + const ETH_CONTRACT_ADDRESS: felt252 = + 0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7; + + #[event] + #[derive(Drop, starknet::Event)] + enum Event { + #[flat] + OwnableEvent: OwnableComponent::Event, + GreetingChanged: GreetingChanged + } + + #[derive(Drop, starknet::Event)] + struct GreetingChanged { + #[key] + greeting_setter: ContractAddress, + #[key] + new_greeting: ByteArray, + premium: bool, + value: u256, + } + + #[storage] + struct Storage { + eth_token: IERC20CamelDispatcher, + greeting: ByteArray, + premium: bool, + total_counter: u256, + user_gretting_counter: LegacyMap, + #[substorage(v0)] + ownable: OwnableComponent::Storage, + } + + #[constructor] + fn constructor(ref self: ContractState, owner: ContractAddress) { + let eth_contract_address = contract_address_const::(); + self.eth_token.write(IERC20CamelDispatcher { contract_address: eth_contract_address }); + self.greeting.write("Building Unstoppable Apps!!!"); + self.ownable.initializer(owner); + } + + #[abi(embed_v0)] + impl YourContractImpl of IYourContract { + fn gretting(self: @ContractState) -> ByteArray { + self.greeting.read() + } + fn set_gretting(ref self: ContractState, new_greeting: ByteArray, amount_eth: u256) { + self.greeting.write(new_greeting); + self.total_counter.write(self.total_counter.read() + 1); + let user_counter = self.user_gretting_counter.read(get_caller_address()); + self.user_gretting_counter.write(get_caller_address(), user_counter + 1); + + if amount_eth > 0 { + // In `Debug Contract` or UI implementation call `approve` on ETH contract before invoke fn set_gretting() + self + .eth_token + .read() + .transferFrom(get_caller_address(), get_contract_address(), amount_eth); + self.premium.write(true); + } else { + self.premium.write(false); + } + self + .emit( + GreetingChanged { + greeting_setter: get_caller_address(), + new_greeting: self.greeting.read(), + premium: true, + value: 100 + } + ); + } + fn withdraw(ref self: ContractState) { + self.ownable.assert_only_owner(); + let balance = self.eth_token.read().balanceOf(get_contract_address()); + self.eth_token.read().transfer(self.ownable.owner(), balance); + } + fn premium(self: @ContractState) -> bool { + self.premium.read() + } + } +} diff --git a/packages/snfoundry/contracts/src/lib.cairo b/packages/snfoundry/contracts/src/lib.cairo index 853bd00aa..568f9f72a 100644 --- a/packages/snfoundry/contracts/src/lib.cairo +++ b/packages/snfoundry/contracts/src/lib.cairo @@ -1,3 +1,4 @@ +mod YourContract; #[cfg(test)] mod test { mod TestContract; diff --git a/packages/snfoundry/contracts/src/test/TestContract.cairo b/packages/snfoundry/contracts/src/test/TestContract.cairo index 8b1378917..e69de29bb 100644 --- a/packages/snfoundry/contracts/src/test/TestContract.cairo +++ b/packages/snfoundry/contracts/src/test/TestContract.cairo @@ -1 +0,0 @@ -