Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ on:
pull_request:
branches:
- main
- develop
paths:
- "packages/nextjs/**"
- "packages/snfoundry/contracts/**"
Expand All @@ -30,7 +31,6 @@ jobs:
with:
node-version: ${{ matrix.node }}
cache: "yarn"
#cache-dependency-path: packages/nextjs/yarn.lock

- name: Install dependencies (Next.js)
run: yarn install --immutable
Expand Down Expand Up @@ -65,7 +65,7 @@ jobs:
working-directory: ./packages/nextjs

- name: Run Next.js tests
run: yarn test run
run: yarn test
working-directory: ./packages/nextjs

- name: Build Next.js project
Expand Down
106 changes: 106 additions & 0 deletions .github/workflows/sync_other_challenges.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
name: Sync other challenges

on:
push:
branches:
- base-challenge-template

jobs:
sync:
runs-on: ubuntu-22.04

steps:
- name: Checkout Repo
uses: actions/checkout@v4
with:
repository: Scaffold-Stark/speedrunstark
token: ${{ secrets.ORG_GITHUB_TOKEN }}
fetch-depth: 0

- name: Setup Git
run: |
git config --global user.name 'github-actions[bot]'
git config --global user.email 'github-actions[bot]@users.noreply.github.com'

git config --local merge.keepmine.name "keep-mine"
git config --local merge.keepmine.driver "true"
git config --local merge.keeptheirs.name "keep-theirs"
git config --local merge.keeptheirs.driver 'cp %B %A'

- name: Update Challenge Branches
run: |
git checkout base-challenge-template
git pull origin base-challenge-template

CHALLENGE_BRANCHES=(
"challenge-0-simple-nft"
"challenge-1-decentralized-staking"
"challenge-2-token-vendor"
"challenge-3-dice-game"
"challenge-4-build-a-dex"
"challenge-5-multisig-wallet"
)

echo "Merging base-challenge-template into challenge branches..."

for branch in "${CHALLENGE_BRANCHES[@]}"; do
echo "Processing branch: $branch"
git checkout $branch
git pull origin $branch

# Try to merge
if git merge base-challenge-template --no-edit; then
echo "Merge successful for $branch, pushing changes"
git push origin $branch
else
echo "Merge conflict detected in $branch, creating PR"
# Abort the current merge
git merge --abort

# Create a new branch for the PR
CONFLICT_BRANCH="fix-conflicts-$branch-$(date +%s)"
git checkout -b $CONFLICT_BRANCH

# Try merge again but allow it to record conflicts
git merge base-challenge-template || true

# Commit the conflicts
git add .
git commit -m "Auto-commit merge conflicts between base-challenge-template and $branch"

# Push the branch with conflicts
git push origin $CONFLICT_BRANCH

# Create PR using GitHub CLI if available, otherwise use API
PR_TITLE="Fix merge conflicts in $branch"
PR_BODY="This PR was automatically created to resolve merge conflicts between base-challenge-template and $branch."

# Using GitHub API to create PR
curl -X POST \
-H "Authorization: token ${{ secrets.ORG_GITHUB_TOKEN }}" \
-H "Accept: application/vnd.github.v3+json" \
https://api.github.com/repos/Scaffold-Stark/speedrunstark/pulls \
-d "{\"title\":\"$PR_TITLE\",\"body\":\"$PR_BODY\",\"head\":\"$CONFLICT_BRANCH\",\"base\":\"$branch\"}"

# Return to original branch
git checkout $branch
fi
done

- name: Notify Slack on Success
if: success()
uses: slackapi/slack-github-action@v1.26.0
with:
channel-id: ${{ secrets.SLACK_CHANNEL_ID }}
slack-message: "Successfully processed sync operation for speedrunstark repository. Check for any PRs that may have been created for conflict resolution."
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: "Failed to sync scaffold-stark-2 changes to speedrunstark repository."
env:
SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }}
4 changes: 2 additions & 2 deletions .tool-versions
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
scarb 2.11.4
starknet-foundry 0.41.0
starknet-devnet 0.4.0
starknet-foundry 0.45.0
starknet-devnet 0.4.3
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "ss-2",
"version": "1.0.11",
"version": "1.0.15",
"author": "Q3 Labs",
"license": "MIT",
"private": true,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import {
isCairoTuple,
isCairoType,
isCairoU256,
isCairoVoid,
} from "~~/utils/scaffold-stark";
import { Struct } from "./Struct";
import { Abi } from "abi-wan-kanabi";
Expand Down Expand Up @@ -98,6 +99,9 @@ export const ContractInput = ({
!isCairoResult(paramType.type) &&
!isCairoOption(paramType.type)
) {
if (isCairoVoid(paramType.type)) {
return <></>;
}
return <InputBase {...inputProps} disabled={isDisabled} />;
} else {
return (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import { AbiFunction } from "~~/utils/scaffold-stark/contract";
import { BlockNumber } from "starknet";
import { useContract, useReadContract } from "@starknet-react/core";
import { ContractInput } from "./ContractInput";
import { isValidContractArgs } from "~~/utils/scaffold-stark/common";

type ReadOnlyFunctionFormProps = {
contractAddress: Address;
Expand All @@ -42,11 +43,16 @@ export const ReadOnlyFunctionForm = ({
address: contractAddress,
});

const inputIsValidArray = isValidContractArgs(
inputValue,
abiFunction.inputs.length,
);

const { isFetching, data, refetch, error } = useReadContract({
address: contractAddress,
functionName: abiFunction.name,
abi: [...abi],
args: inputValue || [],
args: inputIsValidArray ? inputValue : undefined,
enabled: !!inputValue && !!contractInstance,
blockIdentifier: "pending" as BlockNumber,
});
Expand Down Expand Up @@ -76,10 +82,25 @@ export const ReadOnlyFunctionForm = ({

const handleRead = () => {
const newInputValue = getArgsAsStringInputFromForm(form);
const expectedArgCount = abiFunction.inputs.length;

const isValidInput = isValidContractArgs(newInputValue, expectedArgCount);

if (!isValidInput) {
/**
* Todo: add extra logging in future release.
*/
console.warn(
`Read blocked: Expected ${expectedArgCount} args, got ${newInputValue.length}`,
);
return;
}

if (JSON.stringify(form) !== JSON.stringify(lastForm.current)) {
setInputValue(newInputValue);
lastForm.current = form;
}

refetch();
};

Expand Down
30 changes: 15 additions & 15 deletions packages/nextjs/app/debug/_components/contract/utilsContract.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -176,22 +176,22 @@ export const getArgsAsStringInputFromForm = (form: Record<string, any>) => {
}
}

const restructuredEnum = Object.fromEntries(
enumVariants.map((variant) => [
variant,
(enumObject[variant].value || "").trim().length > 0
? _encodeValueFromKey(
(enumObject[variant] as FormStructValue).type,
(enumObject[variant] as FormStructValue).value,
)
: undefined,
]),
);
const activeVariant = enumVariants.find((variant) => {
const v = enumObject[variant];
return v && (v.value !== undefined || v.value === "");
});

if (enumVariants.includes("Some") && enumVariants.includes("None")) {
console.log("options", { restructuredEnum });
console.log("options", "we found an option");
}
const restructuredEnum = activeVariant
? {
[activeVariant]:
enumObject[activeVariant].value !== undefined
? _encodeValueFromKey(
enumObject[activeVariant].type,
enumObject[activeVariant].value,
)
: undefined,
}
: {};

return new CairoCustomEnum(restructuredEnum);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ export function getTopErrorMessage(state: FormErrorMessageState): string {
const baseNumberType = new Set([
"core::integer::u512",
"core::integer::u256",
"core::zeroable::NonZero::<core::integer::u256>",
"core::integer::u128",
"core::integer::u64",
"core::integer::u32",
Expand All @@ -67,6 +68,7 @@ const baseType = new Set([
"core::felt252",
"core::integer::u512",
"core::integer::u256",
"core::zeroable::NonZero::<core::integer::u256>",
"core::integer::u128",
"core::integer::u64",
"core::integer::u32",
Expand Down
39 changes: 18 additions & 21 deletions packages/nextjs/components/scaffold-stark/BlockExplorer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,6 @@ export const BlockExplorer = () => {
img: "/voyager-icon.svg",
link: "https://voyager.online/",
},
{
name: "Stark Compass",
img: "/starkcompass-icon.svg",
link: "https://starkcompass.com/",
},
];

const { resolvedTheme } = useTheme();
Expand All @@ -51,37 +46,39 @@ export const BlockExplorer = () => {
className="modal-toggle"
/>
<GenericModal modalId="blockexplorer-modal">
<div className="flex items-center justify-between">
<h3 className="text-xl font-bold">Mainnet Block Explorers</h3>
<label
htmlFor="blockexplorer-modal"
className="btn btn-ghost btn-sm btn-circle"
>
</label>
</div>
<div className="mb-4 mt-6">
<div className="flex flex-col gap-4">
<div className="space-y-4">
<div className="flex items-center justify-between">
<h3 className="text-xl font-bold">Mainnet Block Explorers</h3>
<label
htmlFor="blockexplorer-modal"
className="btn btn-ghost btn-sm btn-circle"
>
</label>
</div>
<div className="flex flex-col space-y-2">
{blockExplorers.length &&
blockExplorers.map((blockexplorer, id) => (
<a
href={blockexplorer.link}
target="_blank"
className={`h-12 flex items-center btn-sm px-6 gap-4 rounded-[4px] transition-all modal-border ${
isDarkMode ? "hover:bg-[#385183]" : "hover:bg-slate-200"
} border `}
className={`h-10 flex items-center px-4 gap-3 rounded-[4px] transition-all ${
isDarkMode
? "hover:bg-[#385183] border-gray-700"
: "hover:bg-slate-200 border-gray-200"
} border`}
key={id}
>
<div className="flex relative w-6 h-6">
<Image
alt="Starknet Developers Hub"
alt={blockexplorer.name}
className="cursor-pointer"
fill
sizes="1.5rem"
src={blockexplorer.img}
/>
</div>
<span className="text-sm m-0">{blockexplorer.name}</span>
<p className="text-sm m-0">{blockexplorer.name}</p>
</a>
))}
</div>
Expand Down
Loading
Loading