diff --git a/dashboard/hooks/use-simulation-runner.ts b/dashboard/hooks/use-simulation-runner.ts index 6b773b3..12e42af 100644 --- a/dashboard/hooks/use-simulation-runner.ts +++ b/dashboard/hooks/use-simulation-runner.ts @@ -183,15 +183,19 @@ export function useSimulationRunner(policy: PolicySummary) { store.getState().pushLog({ ...entryBase, signature: sig, status: "success", error: null }); } catch (e: unknown) { store.getState().incrementFailed(); - const msg = e instanceof Error ? e.message : String(e); + const err = e as { message?: string; logs?: string[] }; + const baseMsg = err?.message ?? String(e); + const logs = Array.isArray(err?.logs) ? err.logs : []; + const programLog = logs.find((l) => /custom program error|Error Code|Error Number|AnchorError/i.test(l)); + const msg = programLog ? `${baseMsg} — ${programLog}` : baseMsg; store.getState().pushLog({ ...entryBase, signature: null, status: "failed", error: msg }); - if (msg.includes("6000")) { + if (msg.includes("6000") || /PolicyPaused/i.test(msg)) { store.getState().setStopReason("Policy paused (error 6000)"); stop(); return; } - if (msg.includes("6004")) { + if (msg.includes("6004") || /DailyBudgetExceeded/i.test(msg)) { store.getState().setStopReason("Daily budget exceeded (error 6004)"); stop(); return; diff --git a/dashboard/lib/simulation/build-transfer-ix-data.ts b/dashboard/lib/simulation/build-transfer-ix-data.ts index 77056e3..f44919e 100644 --- a/dashboard/lib/simulation/build-transfer-ix-data.ts +++ b/dashboard/lib/simulation/build-transfer-ix-data.ts @@ -1,4 +1,4 @@ -import { Keypair, PublicKey, SystemProgram } from "@solana/web3.js"; +import { Keypair, PublicKey, SystemProgram, Transaction } from "@solana/web3.js"; import { BN } from "@coral-xyz/anchor"; import type { GuardrailsClient } from "@/lib/sdk/client"; @@ -18,18 +18,54 @@ export async function browserGuardedSolTransfer( lamports: number, ): Promise { const ixData = buildTransferIxData(BigInt(lamports)); - return client.guardedExecute( - agentKeypair, - policyPda, - trackerPda, - SystemProgram.programId, - { - instructionData: ixData, - amountHint: new BN(lamports), - inputAccountIndex: null, - }, - [{ pubkey: destination, isSigner: false, isWritable: true }], - ); + const args = { + instructionData: ixData, + amountHint: new BN(lamports), + inputAccountIndex: null, + }; + + const ix = await (client.program.methods as any) + .guardedExecute(args) + .accounts({ + agent: agentKeypair.publicKey, + policy: policyPda, + spendTracker: trackerPda, + targetProgram: SystemProgram.programId, + systemProgram: SystemProgram.programId, + }) + .remainingAccounts([{ pubkey: destination, isSigner: false, isWritable: true }]) + .instruction(); + + const connection = client.program.provider.connection; + const { blockhash, lastValidBlockHeight } = await connection.getLatestBlockhash("confirmed"); + const tx = new Transaction({ feePayer: agentKeypair.publicKey, blockhash, lastValidBlockHeight }).add(ix); + tx.sign(agentKeypair); + + const raw = tx.serialize(); + let sig: string; + try { + sig = await connection.sendRawTransaction(raw, { skipPreflight: false, maxRetries: 0 }); + } catch (e: unknown) { + const sendErr = e as { message?: string; logs?: string[] }; + const logs = Array.isArray(sendErr.logs) ? sendErr.logs : []; + const programLog = logs.find((l) => /custom program error|Error Code|Error Number|AnchorError/i.test(l)); + const baseMsg = sendErr.message ?? String(e); + const err = new Error(programLog ? `${baseMsg} — ${programLog}` : baseMsg) as Error & { logs: string[] }; + err.logs = logs; + throw err; + } + + const conf = await connection.confirmTransaction({ signature: sig, blockhash, lastValidBlockHeight }, "confirmed"); + if (conf.value.err) { + const txDetails = await connection.getTransaction(sig, { commitment: "confirmed" }); + const logs = txDetails?.meta?.logMessages ?? []; + const programLog = logs.find((l) => /custom program error|Error Code|Error Number|AnchorError/i.test(l)); + const errStr = typeof conf.value.err === "string" ? conf.value.err : JSON.stringify(conf.value.err); + const err = new Error(programLog ? `${errStr} — ${programLog}` : errStr) as Error & { logs: string[] }; + err.logs = logs; + throw err; + } + return sig; } export function randomBetween(min: number, max: number): number { diff --git a/landingPage/app/components/defense-bento-section.tsx b/landingPage/app/components/defense-bento-section.tsx index 94868f6..3e47073 100644 --- a/landingPage/app/components/defense-bento-section.tsx +++ b/landingPage/app/components/defense-bento-section.tsx @@ -25,6 +25,129 @@ function Tag({ ) } +function ProgramAllowListIcon() { + return ( + + ) +} + +function SpendingBudgetIcon() { + return ( + + ) +} + +function KillSwitchIcon() { + return ( + + ) +} + +function MonitoringReportsIcon() { + return ( + + ) +} + export default function DefenseBentoSection() { const sectionRef = useRef(null) @@ -98,20 +221,7 @@ export default function DefenseBentoSection() { />
- - - - +

Program Allow-Listing @@ -162,21 +272,7 @@ export default function DefenseBentoSection() { />
- - - - +

Spending Budgets

@@ -216,14 +312,7 @@ export default function DefenseBentoSection() { />

- - - +

AI Kill Switch

@@ -257,22 +346,7 @@ export default function DefenseBentoSection() { />

- - - - +

Real-Time Monitoring & Incident Reports diff --git a/landingPage/app/components/faq-section.tsx b/landingPage/app/components/faq-section.tsx index 6477d68..4057358 100644 --- a/landingPage/app/components/faq-section.tsx +++ b/landingPage/app/components/faq-section.tsx @@ -1,6 +1,6 @@ 'use client' -import { useLayoutEffect, useRef } from 'react' +import { useId, useLayoutEffect, useRef, useState } from 'react' import gsap from 'gsap' import { ScrollTrigger } from 'gsap/ScrollTrigger' @@ -14,7 +14,9 @@ type FaqSectionProps = { } export default function FaqSection({ items }: FaqSectionProps) { + const [openIndex, setOpenIndex] = useState(0) const sectionRef = useRef(null) + const baseId = useId() useLayoutEffect(() => { if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) return @@ -24,17 +26,19 @@ export default function FaqSection({ items }: FaqSectionProps) { const section = sectionRef.current if (!section) return - const cards = section.querySelectorAll('[data-faq-card]') - if (cards.length === 0) return + const accordionItems = section.querySelectorAll( + '[data-faq-item]', + ) + if (accordionItems.length === 0) return - gsap.set(cards, { autoAlpha: 0, y: 20 }) + gsap.set(accordionItems, { autoAlpha: 0, y: 18 }) const trigger = ScrollTrigger.create({ trigger: section, start: 'top 78%', once: true, onEnter: () => { - gsap.to(cards, { + gsap.to(accordionItems, { autoAlpha: 1, y: 0, duration: 0.5, @@ -46,7 +50,7 @@ export default function FaqSection({ items }: FaqSectionProps) { return () => { trigger.kill() - gsap.killTweensOf(cards) + gsap.killTweensOf(accordionItems) } }, []) @@ -65,20 +69,57 @@ export default function FaqSection({ items }: FaqSectionProps) {

-
+
{items.map((item, i) => ( -
-

- {item.question} +

+

-

- {item.answer} -

-
+
+
+
+ {item.answer} +
+
+
+ ))}
diff --git a/landingPage/app/components/final-cta-section.tsx b/landingPage/app/components/final-cta-section.tsx index 706bc02..235529a 100644 --- a/landingPage/app/components/final-cta-section.tsx +++ b/landingPage/app/components/final-cta-section.tsx @@ -18,7 +18,7 @@ export default function FinalCtaSection() {

Protect your agents.
- + Ship with confidence.

diff --git a/landingPage/app/components/hero-section.tsx b/landingPage/app/components/hero-section.tsx index 423d687..31eda8f 100644 --- a/landingPage/app/components/hero-section.tsx +++ b/landingPage/app/components/hero-section.tsx @@ -17,7 +17,7 @@ export default function HeroSection() {

Stop rogue agents.
- + Protect every transaction.

diff --git a/landingPage/app/components/social-proof-bar.tsx b/landingPage/app/components/social-proof-bar.tsx index 7e2d41d..17928dc 100644 --- a/landingPage/app/components/social-proof-bar.tsx +++ b/landingPage/app/components/social-proof-bar.tsx @@ -60,12 +60,12 @@ const proofItems = [ export default function SocialProofBar() { return ( -
+
{proofItems.map((item, i) => (
{i > 0 && ( - + )}
{item.icon}