diff --git a/.github/workflows/ci-cd.yml b/.github/workflows/ci-cd.yml index b2ceb508..4ae0ab12 100644 --- a/.github/workflows/ci-cd.yml +++ b/.github/workflows/ci-cd.yml @@ -2,9 +2,9 @@ name: CI/CD Pipeline on: push: - branches: [ main ] + branches: [main] pull_request: - branches: [ main ] + branches: [main] jobs: check-contracts: @@ -27,16 +27,15 @@ jobs: - name: Add Scarb to PATH run: echo "${HOME}/.local/share/scarb/bin" >> $GITHUB_PATH - # Cache Rust toolchain and dependencies - name: Cache Rust uses: actions/cache@v4 with: path: | ~/.cargo/registry ~/.cargo/git - target/ + ./contracts/target/ key: ${{ runner.os }}-rust-${{ hashFiles('**/Cargo.lock') }} - + - name: Install Rust toolchain uses: actions-rust-lang/setup-rust-toolchain@v1 with: @@ -44,30 +43,37 @@ jobs: targets: wasm32-unknown-unknown profile: minimal - - name: Cache snforge + - name: Cache forge uses: actions/cache@v4 with: - path: ~/.cargo/bin/snforge - key: ${{ runner.os }}-snforge-0.33.0 - - - name: Install snforge + path: ~/.cargo/bin + key: ${{ runner.os }}-forge-${{ hashFiles('**/Cargo.lock') }} + + - name: Install Starknet Foundry (snforge) run: | - if ! command -v snforge &> /dev/null; then - cargo install --locked --git https://github.com/foundry-rs/starknet-foundry \ - --tag v0.33.0 \ - --bin snforge \ - --features=rust-serde + if ! command -v forge &> /dev/null; then + git clone https://github.com/foundry-rs/starknet-foundry.git + cd starknet-foundry + cargo build --release + sudo cp target/release/snforge /usr/local/bin/forge + cd .. + rm -rf starknet-foundry fi - echo "Installed snforge version: $(snforge --version)" - + forge --version + + - name: Install Universal Sierra Compiler + run: curl -L https://raw.githubusercontent.com/software-mansion/universal-sierra-compiler/master/scripts/install.sh | sh + - name: Install dependencies - run: scarb clean && scarb fetch + run: | + scarb clean + scarb fetch - name: Build Starknet contracts run: scarb build - - name: Run snforge tests - run: snforge test --workspace + - name: Run forge tests + run: forge test --workspace nextjs-build-and-test: runs-on: ubuntu-latest @@ -81,9 +87,9 @@ jobs: - name: Setup Node.js uses: actions/setup-node@v4 with: - node-version: '20' - cache: 'npm' - cache-dependency-path: './client/package-lock.json' + node-version: "20" + cache: "npm" + cache-dependency-path: "./client/package-lock.json" - name: Install dependencies run: npm ci @@ -91,9 +97,12 @@ jobs: - name: Lint run: npm run lint + - name: Setup pnpm + run: npm install -g pnpm + - name: Build run: npm run build - env: # Proper indentation here + env: NEXT_PUBLIC_API_URL: ${{ github.event_name == 'pull_request' && 'dummy-api-url' || secrets.NEXT_PUBLIC_API_URL }} OPENAI_API_KEY: ${{ github.event_name == 'pull_request' && 'dummy-key' || secrets.OPENAI_API_KEY }} BRIAN_API_KEY: ${{ github.event_name == 'pull_request' && 'dummy-key' || secrets.BRIAN_API_KEY }} @@ -102,8 +111,8 @@ jobs: uses: actions/cache@v4 with: path: | - client/.next/cache - ${{ github.workspace }}/client/.next/static + ./client/.next/cache + ./client/.next/static key: ${{ runner.os }}-nextjs-${{ hashFiles('client/package-lock.json') }}-${{ hashFiles('client/**.[jt]sx?') }} restore-keys: | ${{ runner.os }}-nextjs-${{ hashFiles('client/package-lock.json') }}- @@ -122,9 +131,9 @@ jobs: - name: Setup Node.js uses: actions/setup-node@v4 with: - node-version: '20' - cache: 'npm' - cache-dependency-path: './client/package-lock.json' + node-version: "20" + cache: "npm" + cache-dependency-path: "./client/package-lock.json" - name: Install dependencies run: npm ci @@ -135,3 +144,5 @@ jobs: NEXT_PUBLIC_API_URL: ${{ secrets.NEXT_PUBLIC_API_URL }} OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} BRIAN_API_KEY: ${{ secrets.BRIAN_API_KEY }} + + diff --git a/.github/workflows/contributors.yml b/.github/workflows/contributors.yml deleted file mode 100644 index 04a50163..00000000 --- a/.github/workflows/contributors.yml +++ /dev/null @@ -1,30 +0,0 @@ -name: Update Contributors - -on: - pull_request: - types: [opened, synchronize, reopened] - -permissions: - contents: write - -jobs: - update-contributors: - runs-on: ubuntu-latest - steps: - - name: Checkout repository - uses: actions/checkout@v3 - - - name: Fetch contributors and update README - run: | - pip install requests - python update_readme.py - env: - TOKEN_GH: ${{ secrets.TOKEN_GH }} - - - name: Commit and push changes - run: | - git config --global user.name "GitHub Actions" - git config --global user.email "actions@github.com" - git add README.md - git commit -m "Update contributors" - git push \ No newline at end of file diff --git a/client/app/agent/transaction/[id]/page.tsx b/client/app/agent/transaction/[id]/page.tsx index 2e2ad601..624a90da 100644 --- a/client/app/agent/transaction/[id]/page.tsx +++ b/client/app/agent/transaction/[id]/page.tsx @@ -18,7 +18,6 @@ import Link from "next/link"; import { TransactionSuccess } from "@/components/TransactionSuccess"; import CommandList from "@/components/ui/command"; import { useState } from "react"; -import { TransactionForm } from "@/components/TransactionForm"; interface UserPreferences { riskTolerance: "low" | "medium" | "high"; @@ -82,9 +81,11 @@ interface MessageContentProps { const TransactionHandler: React.FC = ({ transactions, description, onSuccess, onError }) => { const { account } = useAccount(); + // console.log(account) const [isProcessing, setIsProcessing] = React.useState(false); - + console.log(transactions); const executeTransaction = async () => { + console.log("trying"); if (!account) { onError(new Error("Wallet not connected")); return; @@ -242,6 +243,10 @@ export default function TransactionPage() { const [inputValue, setInputValue] = React.useState(""); const [isLoading, setIsLoading] = React.useState(false); const { address } = useAccount(); + console.log(address); + const { provider } = useProvider(); + console.log(provider.getChainId()); + const scrollRef = React.useRef(null); const [isInputClicked, setIsInputClicked] = React.useState(false); const [showPreferences, setShowPreferences] = useState(false); @@ -270,16 +275,17 @@ export default function TransactionPage() { }, ]); }, []); + // Generates a unique chat ID and navigates to the new chat route. const createNewChat = async () => { - const id = uuidv4(); - await router.push(`/agent/chat/${id}`); + const id = uuidv4(); // Generate a unique ID for the chat session + await router.push(`/agent/chat/${id}`); // Navigate to the new chat route }; -// Generates a unique chat ID and navigates to the new Transaction route. - const createNewTxn = async () => { - const id = uuidv4(); // Generate a unique ID for the transaction session - await router.push(`/agent/transaction/${id}`); // Navigate to the new transaction route - }; + // Generates a unique chat ID and navigates to the new Transaction route. + const createNewTxn = async () => { + const id = uuidv4(); // Generate a unique ID for the transaction session + await router.push(`/agent/transaction/${id}`); // Navigate to the new transaction route + }; const handleTransactionSuccess = (hash: string) => { const successMessage: Message = { @@ -315,33 +321,33 @@ export default function TransactionPage() { user: "User", }; - setMessages((prev) => [...prev, userMessage]); - setInputValue(""); - setIsLoading(true); - - const controller = new AbortController(); - const timeoutId = setTimeout(() => controller.abort(), 135000); // 35 seconds - - try { - const response = await fetch("/api/transactions", { - method: "POST", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify({ - prompt: inputValue, - address: address, - messages: messages, - userPreferences, - stream: true, - }), - signal: controller.signal, - }); - - const data = await response.json(); - console.log(data); - - clearTimeout(timeoutId); // Clear timeout if fetch succeeds + setMessages((prev) => [...prev, userMessage]); + setInputValue(""); + setIsLoading(true); + + const controller = new AbortController(); + const timeoutId = setTimeout(() => controller.abort(), 135000); // 35 seconds + + try { + const response = await fetch("/api/transactions", { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + prompt: inputValue, + address: address, + messages: messages, + userPreferences, + stream: true, + }), + signal: controller.signal, + }); + + const data = await response.json(); + console.log(data); + + clearTimeout(timeoutId); // Clear timeout if fetch succeeds let agentMessage: Message; @@ -377,62 +383,60 @@ export default function TransactionPage() { }; } - setMessages((prev) => [...prev, agentMessage]); - } catch (error) { - if ((error instanceof Error) && error.name === "AbortError") { - console.error("Frontend fetch request timed out"); - } else { - console.error("Error:", error); - } - const errorMessage: Message = { - id: uuidv4(), - role: "agent", - content: "Sorry, something went wrong. Please try again.", - timestamp: new Date().toLocaleTimeString(), - user: "Agent", - }; - setMessages((prev) => [...prev, errorMessage]); - } finally { - setIsLoading(false); - } - }; - - - - return ( -
- {/* Dotted background */} -
- - {/* Content wrapper */} -
- {/* Sidebar */} -
-

StarkFinder

- - - - {/* + setMessages((prev) => [...prev, agentMessage]); + } catch (error) { + if (error instanceof Error && error.name === "AbortError") { + console.error("Frontend fetch request timed out"); + } else { + console.error("Error:", error); + } + const errorMessage: Message = { + id: uuidv4(), + role: "agent", + content: "Sorry, something went wrong. Please try again.", + timestamp: new Date().toLocaleTimeString(), + user: "Agent", + }; + setMessages((prev) => [...prev, errorMessage]); + } finally { + setIsLoading(false); + } + }; + + return ( +
+ {/* Dotted background */} +
+ + {/* Content wrapper */} +
+ {/* Sidebar */} +
+

StarkFinder

+ + + + {/*
-
- {address ? ( - <> -
- Online - - ) : ( - <> -
- Offline - - )} -
-
- - {/* Main Content */} -
- {/* Header */} -
-
- - - Home - -

StarkFinder - Transactions

-
-
- {address ? ( -
-
- {`${address.slice(0, 5)}...${address.slice(-3)}`} -
- -
- ) : ( - - )} -
-
+
+ {address ? ( + <> +
+ Online + + ) : ( + <> +
+ Offline + + )} +
+
+ + {/* Main Content */} +
+ {/* Header */} +
+
+ + + Home + +

StarkFinder - Transactions

+
+
+ {address ? ( +
+
{`${address?.slice(0, 5)}...${address?.slice(-3)}`}
+ +
+ ) : ( + + )} +
+
{/* Chat Area */} @@ -553,7 +557,17 @@ export default function TransactionPage() {
- {isInputClicked && } + {isInputClicked && ( + + )} {/* Input Area */}
diff --git a/client/components/playground/floatingWindow/FloatingSidebar.tsx b/client/components/playground/floatingWindow/FloatingSidebar.tsx index e57fddde..ac3db8bc 100644 --- a/client/components/playground/floatingWindow/FloatingSidebar.tsx +++ b/client/components/playground/floatingWindow/FloatingSidebar.tsx @@ -1,15 +1,17 @@ +"use client"; + /* eslint-disable react/jsx-key */ /* eslint-disable @typescript-eslint/no-unused-vars */ /* eslint-disable @typescript-eslint/no-explicit-any */ import { useState, useReducer } from "react"; import groupedBlocks from "./data"; import { useForm } from "react-hook-form"; -import { zodResolver } from "@hookform/resolvers/zod" -import { toast } from 'sonner' -import { z } from 'zod' +import { zodResolver } from "@hookform/resolvers/zod"; +import { toast } from "sonner"; +import { z } from "zod"; // libraries -import clsx from 'clsx'; +import clsx from "clsx"; // icons import StartIcon from "@/components/svgs/StartIcon"; @@ -21,10 +23,10 @@ import StakeTokenIcon from "@/components/svgs/StakeTokenIcon"; import YieldFarmingIcon from "@/components/svgs/YieldFarmingIcon"; import AllocateTokenIcon from "@/components/svgs/AllocateTokenIcon"; import LendTokenIcon from "@/components/svgs/LendTokenIcon"; -import BagIcon from "@/components/svgs/BagIcon" +import BagIcon from "@/components/svgs/BagIcon"; import CubeIcon from "@/components/svgs/CubeIcon"; -import LiquidDropIcon from "@/components/svgs/LiquidDropIcon" -import AddIcon from "@/components/svgs/AddIcon" +import LiquidDropIcon from "@/components/svgs/LiquidDropIcon"; +import AddIcon from "@/components/svgs/AddIcon"; import AnalyticsIcon from "@/components/svgs/AnalyticsIcon"; import BorrowTokenIcon from "@/components/svgs/BorrowTokenIcon"; import ClockIcon from "@/components/svgs/ClockIcon"; @@ -58,39 +60,80 @@ interface FloatingSidebarProps { // blockName: z.string().min(1, "Block name is required"), // solidityCode: z.string().min(1, "Solidity code is required"), // }) -const greg = groupedBlocks["Trigger Actions"] -const token = groupedBlocks["Token Actions"] -const li = groupedBlocks["Liquidity"] -const po = groupedBlocks["Portfolio Management"] -const inst = groupedBlocks["Analytics"] -const go = groupedBlocks["Governance"] -const ev = groupedBlocks["Events"] -const triggerActions = [{ icon: , text: "Initialise", toggle: false, groupedBlock: groupedBlocks["Trigger Actions"] }, { icon: , text: "Connection", toggle: true, groupedBlock: groupedBlocks["Trigger Actions"] }]; - -const tokenActions = [{ icon: , text: "Swap Token", toggle: false }, { icon: , text: "StakeToken", toggle: false }, { icon: , text: "Allocate Token", toggle: false }, { icon: , text: "Yield Farming", toggle: true }, { icon: , text: "Lend Tokens", toggle: false }, { icon: , text: "Borrow Token", toggle: false }, { icon: , text: "Repay Loan", toggle: false }]; - -const liquidityManagement = [{ icon: , text: "Add Liquidity" }, { icon: , text: "Create Stack Pooling" }] - -const portfolioManagement = [{ icon: , text: "rebalance Portfolio" }, { icon: , text: "Set Rebalance" }, { icon: , text: "Create Custom Index" }, { icon: , text: "Set Stop Loss" }, { icon: , text: "Set Take Profit" }, { icon: , text: "Set Strategy" }] - -const insighAndAnalytics = [{ icon: , text: "Check Transaction" }, { icon: , text: "Portfolio Analytics" }] - -const governance = [{ icon: , text: "Vote on Proposal" }, { icon: , text: "Create Vesting" }] - -const eventsAndAutomation = [{ icon: , text: "On Event Outcome" }, { icon: , text: "Execute Flash Loan" }, { icon: , text: "Initiate Airdrop" }] +const greg = groupedBlocks["Trigger Actions"]; +const token = groupedBlocks["Token Actions"]; +const li = groupedBlocks["Liquidity"]; +const po = groupedBlocks["Portfolio Management"]; +const inst = groupedBlocks["Analytics"]; +const go = groupedBlocks["Governance"]; +const ev = groupedBlocks["Events"]; +const triggerActions = [ + { + icon: , + text: "Initialise", + toggle: false, + groupedBlock: groupedBlocks["Trigger Actions"], + }, + { + icon: , + text: "Connection", + toggle: true, + groupedBlock: groupedBlocks["Trigger Actions"], + }, +]; + +const tokenActions = [ + { icon: , text: "Swap Token", toggle: false }, + { icon: , text: "StakeToken", toggle: false }, + { icon: , text: "Allocate Token", toggle: false }, + { icon: , text: "Yield Farming", toggle: true }, + { icon: , text: "Lend Tokens", toggle: false }, + { icon: , text: "Borrow Token", toggle: false }, + { icon: , text: "Repay Loan", toggle: false }, +]; + +const liquidityManagement = [ + { icon: , text: "Add Liquidity" }, + { icon: , text: "Create Stack Pooling" }, +]; + +const portfolioManagement = [ + { icon: , text: "rebalance Portfolio" }, + { icon: , text: "Set Rebalance" }, + { icon: , text: "Create Custom Index" }, + { icon: , text: "Set Stop Loss" }, + { icon: , text: "Set Take Profit" }, + { icon: , text: "Set Strategy" }, +]; + +const insighAndAnalytics = [ + { icon: , text: "Check Transaction" }, + { icon: , text: "Portfolio Analytics" }, +]; + +const governance = [ + { icon: , text: "Vote on Proposal" }, + { icon: , text: "Create Vesting" }, +]; + +const eventsAndAutomation = [ + { icon: , text: "On Event Outcome" }, + { icon: , text: "Execute Flash Loan" }, + { icon: , text: "Initiate Airdrop" }, +]; interface FloatingSidebarProps { addBlock: (block: any) => void; } interface ToggleState { - triggerActionToggle: boolean, - tokenActionsToggle: boolean, - liquidityManagementToggle: boolean, - portfolioManagementToggle: boolean, - insightAndAnalyticsToggle: boolean, - governanceToggle: boolean, - eventsAndAutomationToggle: boolean + triggerActionToggle: boolean; + tokenActionsToggle: boolean; + liquidityManagementToggle: boolean; + portfolioManagementToggle: boolean; + insightAndAnalyticsToggle: boolean; + governanceToggle: boolean; + eventsAndAutomationToggle: boolean; } type ToggleAction = @@ -100,7 +143,7 @@ type ToggleAction = | { type: "toggle_portfolioManagement" } | { type: "toggle_insightAndAnalytics" } | { type: "toggle_governance" } - | { type: "toggle_eventsAndAutomation" } + | { type: "toggle_eventsAndAutomation" }; const initialState = { triggerActionToggle: false, @@ -109,30 +152,44 @@ const initialState = { portfolioManagementToggle: false, insightAndAnalyticsToggle: false, governanceToggle: false, - eventsAndAutomationToggle: false -} + eventsAndAutomationToggle: false, +}; const combined = triggerActions.map((action, index) => ({ ...action, block: greg[index], })); - function toggleReducer(state: ToggleState, action: ToggleAction): ToggleState { switch (action.type) { case "toggle_triggerAction": - return { ...initialState, triggerActionToggle: !state.triggerActionToggle }; + return { + ...initialState, + triggerActionToggle: !state.triggerActionToggle, + }; case "toggle_tokenActions": return { ...initialState, tokenActionsToggle: !state.tokenActionsToggle }; case "toggle_liquidityManagement": - return { ...initialState, liquidityManagementToggle: !state.liquidityManagementToggle }; + return { + ...initialState, + liquidityManagementToggle: !state.liquidityManagementToggle, + }; case "toggle_portfolioManagement": - return { ...initialState, portfolioManagementToggle: !state.portfolioManagementToggle } + return { + ...initialState, + portfolioManagementToggle: !state.portfolioManagementToggle, + }; case "toggle_insightAndAnalytics": - return { ...initialState, insightAndAnalyticsToggle: !state.insightAndAnalyticsToggle }; + return { + ...initialState, + insightAndAnalyticsToggle: !state.insightAndAnalyticsToggle, + }; case "toggle_governance": return { ...initialState, governanceToggle: !state.governanceToggle }; case "toggle_eventsAndAutomation": - return { ...initialState, eventsAndAutomationToggle: !state.eventsAndAutomationToggle }; + return { + ...initialState, + eventsAndAutomationToggle: !state.eventsAndAutomationToggle, + }; default: return initialState; } @@ -149,7 +206,11 @@ const formSchema = z.object({ cairoCode: z.string().min(1, "Cairo code is required"), }); -function CustomBlockModal({ isOpen, onClose, onSubmit }: CustomBlockModalProps) { +function CustomBlockModal({ + isOpen, + onClose, + onSubmit, +}: CustomBlockModalProps) { const form = useForm({ resolver: zodResolver(formSchema), defaultValues: { @@ -166,24 +227,32 @@ function CustomBlockModal({ isOpen, onClose, onSubmit }: CustomBlockModalProps)

Create Custom Block

- + {form.formState.errors.blockName && ( -

{form.formState.errors.blockName.message}

+

+ {form.formState.errors.blockName.message} +

)}
- +