diff --git a/.github/workflows/django-tests.yml b/.github/workflows/django-tests.yml
index efa30f8c6..6fbe81387 100644
--- a/.github/workflows/django-tests.yml
+++ b/.github/workflows/django-tests.yml
@@ -36,15 +36,15 @@ jobs:
--health-retries 5
steps:
- - uses: actions/checkout@v3
+ - uses: actions/checkout@v4
- name: Set up Python
- uses: actions/setup-python@v4
+ uses: actions/setup-python@v5
with:
python-version: "3.11"
- name: Cache pip packages
- uses: actions/cache@v3
+ uses: actions/cache@v4
with:
path: ~/.cache/pip
key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }}
@@ -69,7 +69,7 @@ jobs:
pytest --cov=soroscan.ingest --cov-report=term-missing --cov-report=xml --cov-fail-under=80
- name: Upload coverage reports
- uses: codecov/codecov-action@v3
+ uses: codecov/codecov-action@v4
with:
file: ./django-backend/coverage.xml
flags: backend
diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml
new file mode 100644
index 000000000..0f158a479
--- /dev/null
+++ b/.github/workflows/e2e.yml
@@ -0,0 +1,34 @@
+name: E2E Tests
+on: [push, pull_request]
+
+jobs:
+ e2e:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+ - uses: pnpm/action-setup@v4
+ with:
+ version: 9
+ - uses: actions/setup-node@v4
+ with:
+ node-version: 20
+ cache: 'pnpm'
+ cache-dependency-path: 'soroscan-frontend/pnpm-lock.yaml'
+ - name: Install dependencies
+ run: pnpm install --frozen-lockfile
+ working-directory: soroscan-frontend
+ - name: Install Playwright Browsers
+ run: npx playwright install --with-deps
+ working-directory: soroscan-frontend
+ - name: Build
+ run: pnpm run build
+ working-directory: soroscan-frontend
+ - name: Run Playwright tests
+ run: npx playwright test
+ working-directory: soroscan-frontend
+ - uses: actions/upload-artifact@v4
+ if: always()
+ with:
+ name: playwright-report
+ path: soroscan-frontend/playwright-report/
+ retention-days: 30
diff --git a/soroscan-frontend/app/contracts/[id]/components/BackfillModal.tsx b/soroscan-frontend/app/contracts/[contractId]/components/BackfillModal.tsx
similarity index 100%
rename from soroscan-frontend/app/contracts/[id]/components/BackfillModal.tsx
rename to soroscan-frontend/app/contracts/[contractId]/components/BackfillModal.tsx
diff --git a/soroscan-frontend/app/contracts/[id]/components/ContractForm.tsx b/soroscan-frontend/app/contracts/[contractId]/components/ContractForm.tsx
similarity index 97%
rename from soroscan-frontend/app/contracts/[id]/components/ContractForm.tsx
rename to soroscan-frontend/app/contracts/[contractId]/components/ContractForm.tsx
index 8a6f44c62..45d8e2678 100644
--- a/soroscan-frontend/app/contracts/[id]/components/ContractForm.tsx
+++ b/soroscan-frontend/app/contracts/[contractId]/components/ContractForm.tsx
@@ -141,11 +141,11 @@ export function ContractForm({ contract, onSave, onCancel }: ContractFormProps)
)}
-
+
-
diff --git a/soroscan-frontend/app/contracts/[contractId]/events/explorer/page.tsx b/soroscan-frontend/app/contracts/[contractId]/events/explorer/page.tsx
new file mode 100644
index 000000000..c1ee10691
--- /dev/null
+++ b/soroscan-frontend/app/contracts/[contractId]/events/explorer/page.tsx
@@ -0,0 +1,10 @@
+import { EventExplorerView } from "@/components/ingest/EventExplorerView";
+
+export default function ContractExplorerPage({
+ params,
+}: {
+ params: { contractId: string };
+}) {
+ const { contractId } = params;
+ return
;
+}
diff --git a/soroscan-frontend/app/contracts/[contractId]/page.tsx b/soroscan-frontend/app/contracts/[contractId]/page.tsx
index 3120f16c1..4c7369aa2 100644
--- a/soroscan-frontend/app/contracts/[contractId]/page.tsx
+++ b/soroscan-frontend/app/contracts/[contractId]/page.tsx
@@ -127,18 +127,16 @@ export default function ContractDetailPage({ params }: { params: { contractId: s
Status
{contract.status.toUpperCase()}
diff --git a/soroscan-frontend/app/contracts/[id]/timeline/page.tsx b/soroscan-frontend/app/contracts/[contractId]/timeline/page.tsx
similarity index 53%
rename from soroscan-frontend/app/contracts/[id]/timeline/page.tsx
rename to soroscan-frontend/app/contracts/[contractId]/timeline/page.tsx
index 05e6dca37..cd0cbf803 100644
--- a/soroscan-frontend/app/contracts/[id]/timeline/page.tsx
+++ b/soroscan-frontend/app/contracts/[contractId]/timeline/page.tsx
@@ -3,8 +3,8 @@ import { TimelineView } from "@/components/ingest/TimelineView";
export default function ContractTimelinePage({
params,
}: {
- params: { id: string };
+ params: { contractId: string };
}) {
- const { id } = params;
- return
;
+ const { contractId } = params;
+ return
;
}
diff --git a/soroscan-frontend/app/contracts/[id]/events/explorer/page.tsx b/soroscan-frontend/app/contracts/[id]/events/explorer/page.tsx
deleted file mode 100644
index f2ffe9b12..000000000
--- a/soroscan-frontend/app/contracts/[id]/events/explorer/page.tsx
+++ /dev/null
@@ -1,10 +0,0 @@
-import { EventExplorerView } from "@/components/ingest/EventExplorerView";
-
-export default function ContractExplorerPage({
- params,
-}: {
- params: { id: string };
-}) {
- const { id } = params;
- return
;
-}
diff --git a/soroscan-frontend/app/contracts/[id]/page.tsx b/soroscan-frontend/app/contracts/[id]/page.tsx
deleted file mode 100644
index 091696557..000000000
--- a/soroscan-frontend/app/contracts/[id]/page.tsx
+++ /dev/null
@@ -1,206 +0,0 @@
-"use client";
-
-import * as React from "react";
-import { useRouter } from "next/navigation";
-import { Card } from "@/components/terminal/Card";
-import { Button } from "@/components/terminal/Button";
-import { ContractForm } from "./components/ContractForm";
-import { BackfillModal } from "./components/BackfillModal";
-import {
- getContract,
- updateContract,
- triggerBackfill,
-} from "@/components/ingest/contract-graphql";
-import type { Contract, ContractFormData, BackfillTask } from "@/components/ingest/contract-types";
-
-export default function ContractDetailPage({ params }: { params: { id: string } }) {
- const router = useRouter();
- const [contract, setContract] = React.useState
(null);
- const [isLoading, setIsLoading] = React.useState(true);
- const [isEditing, setIsEditing] = React.useState(false);
- const [backfillTask, setBackfillTask] = React.useState(null);
- const [isBackfillModalOpen, setIsBackfillModalOpen] = React.useState(false);
- const [error, setError] = React.useState(null);
-
- const loadContract = React.useCallback(async () => {
- try {
- setIsLoading(true);
- setError(null);
- const data = await getContract(params.id);
- setContract(data);
- } catch (err) {
- setError(err instanceof Error ? err.message : "Failed to load contract");
- } finally {
- setIsLoading(false);
- }
- }, [params.id]);
-
- React.useEffect(() => {
- loadContract();
- }, [loadContract]);
-
- const handleSave = async (data: ContractFormData) => {
- const updated = await updateContract(params.id, data);
- setContract(updated);
- setIsEditing(false);
- };
-
- const handleBackfill = async () => {
- if (!contract) return;
-
- try {
- const task = await triggerBackfill(contract.contractId);
- setBackfillTask(task);
- setIsBackfillModalOpen(true);
- } catch (err) {
- setError(err instanceof Error ? err.message : "Failed to trigger backfill");
- }
- };
-
- if (isLoading) {
- return (
-
- );
- }
-
- if (!contract) {
- return (
-
-
-
-
- Contract not found
-
-
-
-
- );
- }
-
- return (
-
-
-
-
-
- [CONTRACT_DETAIL]
-
-
- {contract.contractId}
-
-
-
router.push("/contracts")}>
- Back to List
-
-
-
- {error && (
-
-
- {error}
-
-
- )}
-
-
- {isEditing ? (
- setIsEditing(false)}
- />
- ) : (
-
-
-
-
Name
-
{contract.name}
-
-
-
Status
-
-
- {contract.status.toUpperCase()}
-
-
-
-
- {contract.description && (
-
-
Description
-
- {contract.description}
-
-
- )}
-
-
-
Event Count
-
- {contract.eventCount.toLocaleString()}
-
-
-
- {contract.tags && contract.tags.length > 0 && (
-
-
Tags
-
- {contract.tags.map((tag) => (
-
- {tag}
-
- ))}
-
-
- )}
-
-
- setIsEditing(true)}>
- Edit Contract
-
-
- Trigger Backfill
-
- router.push(`/contracts/${contract.contractId}/events/explorer`)}
- >
- View Events
-
-
-
- )}
-
-
-
setIsBackfillModalOpen(false)}
- task={backfillTask}
- />
-
-
- );
-}
diff --git a/soroscan-frontend/jest.config.ts b/soroscan-frontend/jest.config.ts
index e782bf90a..5f08d0e4b 100644
--- a/soroscan-frontend/jest.config.ts
+++ b/soroscan-frontend/jest.config.ts
@@ -10,6 +10,7 @@ const createJestConfig = nextJest({
const config: Config = {
coverageProvider: 'v8',
testEnvironment: 'jsdom',
+ testPathIgnorePatterns: ['/tests/'],
// Add more setup options before each test is run
setupFilesAfterEnv: ['/jest.setup.ts'],
moduleNameMapper: {
diff --git a/soroscan-frontend/package-lock.json b/soroscan-frontend/package-lock.json
index cf2b44b26..cedc4af4e 100644
--- a/soroscan-frontend/package-lock.json
+++ b/soroscan-frontend/package-lock.json
@@ -28,6 +28,7 @@
"@graphql-codegen/client-preset": "^5.2.3",
"@graphql-codegen/typescript": "^5.0.8",
"@graphql-codegen/typescript-operations": "^5.0.8",
+ "@playwright/test": "^1.58.2",
"@tailwindcss/postcss": "^4",
"@testing-library/dom": "^10.4.1",
"@testing-library/jest-dom": "^6.9.1",
@@ -4017,6 +4018,22 @@
"url": "https://opencollective.com/pkgr"
}
},
+ "node_modules/@playwright/test": {
+ "version": "1.58.2",
+ "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.58.2.tgz",
+ "integrity": "sha512-akea+6bHYBBfA9uQqSYmlJXn61cTa+jbO87xVLCWbTqbWadRVmhxlXATaOjOgcBaWU4ePo0wB41KMFv3o35IXA==",
+ "devOptional": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "playwright": "1.58.2"
+ },
+ "bin": {
+ "playwright": "cli.js"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
"node_modules/@radix-ui/number": {
"version": "1.1.1",
"license": "MIT"
@@ -13813,6 +13830,53 @@
"node": ">=8"
}
},
+ "node_modules/playwright": {
+ "version": "1.58.2",
+ "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.58.2.tgz",
+ "integrity": "sha512-vA30H8Nvkq/cPBnNw4Q8TWz1EJyqgpuinBcHET0YVJVFldr8JDNiU9LaWAE1KqSkRYazuaBhTpB5ZzShOezQ6A==",
+ "devOptional": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "playwright-core": "1.58.2"
+ },
+ "bin": {
+ "playwright": "cli.js"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "optionalDependencies": {
+ "fsevents": "2.3.2"
+ }
+ },
+ "node_modules/playwright-core": {
+ "version": "1.58.2",
+ "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.58.2.tgz",
+ "integrity": "sha512-yZkEtftgwS8CsfYo7nm0KE8jsvm6i/PTgVtB8DL726wNf6H2IMsDuxCpJj59KDaxCtSnrWan2AeDqM7JBaultg==",
+ "devOptional": true,
+ "license": "Apache-2.0",
+ "bin": {
+ "playwright-core": "cli.js"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/playwright/node_modules/fsevents": {
+ "version": "2.3.2",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
+ "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
+ "dev": true,
+ "hasInstallScript": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
+ }
+ },
"node_modules/possible-typed-array-names": {
"version": "1.1.0",
"dev": true,
diff --git a/soroscan-frontend/package.json b/soroscan-frontend/package.json
index 678a46706..de2c89713 100644
--- a/soroscan-frontend/package.json
+++ b/soroscan-frontend/package.json
@@ -11,7 +11,8 @@
"test:watch": "jest --watch",
"test:ci": "jest --ci",
"codegen": "graphql-codegen --config codegen.ts",
- "codegen:watch": "graphql-codegen --config codegen.ts --watch"
+ "codegen:watch": "graphql-codegen --config codegen.ts --watch",
+ "test:e2e": "npx playwright test"
},
"dependencies": {
"@apollo/client": "^3.14.0",
@@ -34,6 +35,7 @@
"@graphql-codegen/client-preset": "^5.2.3",
"@graphql-codegen/typescript": "^5.0.8",
"@graphql-codegen/typescript-operations": "^5.0.8",
+ "@playwright/test": "^1.58.2",
"@tailwindcss/postcss": "^4",
"@testing-library/dom": "^10.4.1",
"@testing-library/jest-dom": "^6.9.1",
diff --git a/soroscan-frontend/playwright-report/data/1acaabc0b1d1dddf0e73eba5f78b7b6fca8f201b.png b/soroscan-frontend/playwright-report/data/1acaabc0b1d1dddf0e73eba5f78b7b6fca8f201b.png
new file mode 100644
index 000000000..843a1e1a4
Binary files /dev/null and b/soroscan-frontend/playwright-report/data/1acaabc0b1d1dddf0e73eba5f78b7b6fca8f201b.png differ
diff --git a/soroscan-frontend/playwright-report/data/55bd9169f0f33d420f7c1a18d3df67faa8caf8e1.md b/soroscan-frontend/playwright-report/data/55bd9169f0f33d420f7c1a18d3df67faa8caf8e1.md
new file mode 100644
index 000000000..4e36224f1
--- /dev/null
+++ b/soroscan-frontend/playwright-report/data/55bd9169f0f33d420f7c1a18d3df67faa8caf8e1.md
@@ -0,0 +1,86 @@
+# Page snapshot
+
+```yaml
+- generic [ref=e1]:
+ - generic [active]:
+ - generic [ref=e4]:
+ - generic [ref=e5]:
+ - generic [ref=e6]:
+ - navigation [ref=e7]:
+ - button "previous" [disabled] [ref=e8]:
+ - img "previous" [ref=e9]
+ - generic [ref=e11]:
+ - generic [ref=e12]: 1/
+ - text: "1"
+ - button "next" [disabled] [ref=e13]:
+ - img "next" [ref=e14]
+ - img
+ - generic [ref=e16]:
+ - generic [ref=e17]:
+ - img [ref=e18]
+ - generic "Latest available version is detected (16.1.6)." [ref=e20]: Next.js 16.1.6
+ - generic [ref=e21]: Turbopack
+ - img
+ - dialog "Runtime TypeError" [ref=e23]:
+ - generic [ref=e26]:
+ - generic [ref=e27]:
+ - generic [ref=e28]:
+ - generic [ref=e30]: Runtime TypeError
+ - generic [ref=e31]:
+ - button "Copy Error Info" [ref=e32] [cursor=pointer]:
+ - img [ref=e33]
+ - button "No related documentation found" [disabled] [ref=e35]:
+ - img [ref=e36]
+ - button "Attach Node.js inspector" [ref=e38] [cursor=pointer]:
+ - img [ref=e39]
+ - generic [ref=e48]: can't access property "length", contracts is undefined
+ - generic [ref=e49]:
+ - generic [ref=e50]:
+ - paragraph [ref=e52]:
+ - img [ref=e54]
+ - generic [ref=e57]: app/contracts/components/ContractTable.tsx (40:17) @ ContractTable
+ - button "Open in editor" [ref=e58] [cursor=pointer]:
+ - img [ref=e60]
+ - generic [ref=e63]:
+ - generic [ref=e64]: 38 |
+ - generic [ref=e65]: 39 |
+ - generic [ref=e66]: "> 40 | "
+ - generic [ref=e67]: "| ^"
+ - generic [ref=e68]: "41 | {contracts.length === 0 ? ("
+ - generic [ref=e69]: 42 |
+ - generic [ref=e70]: "43 | "
+ - generic [ref=e71]:
+ - generic [ref=e72]:
+ - paragraph [ref=e73]:
+ - text: Call Stack
+ - generic [ref=e74]: "59"
+ - button "Show 57 ignore-listed frame(s)" [ref=e75] [cursor=pointer]:
+ - text: Show 57 ignore-listed frame(s)
+ - img [ref=e76]
+ - generic [ref=e78]:
+ - generic [ref=e79]:
+ - text: ContractTable
+ - button "Open ContractTable in editor" [ref=e80] [cursor=pointer]:
+ - img [ref=e81]
+ - text: app/contracts/components/ContractTable.tsx (40:17)
+ - generic [ref=e83]:
+ - generic [ref=e84]:
+ - text: ContractsPage
+ - button "Open ContractsPage in editor" [ref=e85] [cursor=pointer]:
+ - img [ref=e86]
+ - text: app/contracts/page.tsx (99:13)
+ - generic [ref=e88]: "1"
+ - generic [ref=e89]: "2"
+ - generic [ref=e94] [cursor=pointer]:
+ - button "Open Next.js Dev Tools" [ref=e95]:
+ - img [ref=e96]
+ - generic [ref=e100]:
+ - button "Open issues overlay" [ref=e101]:
+ - generic [ref=e102]:
+ - generic [ref=e103]: "0"
+ - generic [ref=e104]: "1"
+ - generic [ref=e105]: Issue
+ - button "Collapse issues badge" [ref=e106]:
+ - img [ref=e107]
+ - 'heading "Application error: a client-side exception has occurred while loading localhost (see the browser console for more information)." [level=2] [ref=e111]'
+```
\ No newline at end of file
diff --git a/soroscan-frontend/playwright-report/data/5ebd38f920b8f87b7183eb16c02f1733aea3e5be.png b/soroscan-frontend/playwright-report/data/5ebd38f920b8f87b7183eb16c02f1733aea3e5be.png
new file mode 100644
index 000000000..d3ea64e03
Binary files /dev/null and b/soroscan-frontend/playwright-report/data/5ebd38f920b8f87b7183eb16c02f1733aea3e5be.png differ
diff --git a/soroscan-frontend/playwright-report/data/618c314b21e418d597cc98bbc2cb573cd96d15a1.md b/soroscan-frontend/playwright-report/data/618c314b21e418d597cc98bbc2cb573cd96d15a1.md
new file mode 100644
index 000000000..52c72f47b
--- /dev/null
+++ b/soroscan-frontend/playwright-report/data/618c314b21e418d597cc98bbc2cb573cd96d15a1.md
@@ -0,0 +1,99 @@
+# Page snapshot
+
+```yaml
+- generic [ref=e1]:
+ - main [ref=e3]:
+ - generic [ref=e4]:
+ - paragraph [ref=e5]: SoroScan
+ - heading "Event Explorer Dashboard" [level=1] [ref=e6]
+ - paragraph [ref=e7]: Browse, filter, and analyze contract events in real-time
+ - region "Event filters" [ref=e8]:
+ - generic [ref=e9]:
+ - heading "Filters" [level=2] [ref=e10]
+ - generic [ref=e11]:
+ - generic [ref=e12]:
+ - generic [ref=e13]: Contract
+ - combobox "Contract" [ref=e14]:
+ - option "All Contracts"
+ - option "Test Token" [selected]
+ - option "Liquidity Pool"
+ - generic [ref=e15]:
+ - generic [ref=e16]: Event Type
+ - combobox "Event Type" [ref=e17]:
+ - option "All Types" [selected]
+ - option "SWAP"
+ - option "MINT"
+ - option "BURN"
+ - option "TRANSFER"
+ - generic [ref=e18]:
+ - generic [ref=e19]: From
+ - textbox "From" [ref=e20]
+ - generic [ref=e21]:
+ - generic [ref=e22]: To
+ - textbox "To" [ref=e23]
+ - generic [ref=e25]:
+ - generic [ref=e26]: Search
+ - textbox "Search" [ref=e27]:
+ - /placeholder: Search events...
+ - generic [ref=e28]:
+ - button "Apply Filters" [active] [ref=e29] [cursor=pointer]
+ - button "Clear" [ref=e30] [cursor=pointer]
+ - button "Export CSV" [ref=e31] [cursor=pointer]
+ - button "Export JSON" [ref=e32] [cursor=pointer]
+ - region "Events table" [ref=e33]:
+ - generic [ref=e34]:
+ - heading "Contract Events" [level=2] [ref=e35]
+ - paragraph [ref=e36]: Showing 1-2 of 2+
+ - table [ref=e38]:
+ - rowgroup [ref=e39]:
+ - row "Contract Type Ledger Time Transaction Actions" [ref=e40]:
+ - columnheader "Contract" [ref=e41]
+ - columnheader "Type" [ref=e42]
+ - columnheader "Ledger" [ref=e43]
+ - columnheader "Time" [ref=e44]
+ - columnheader "Transaction" [ref=e45]
+ - columnheader "Actions" [ref=e46]
+ - rowgroup [ref=e47]:
+ - row "CABC1234...567890 📋 SWAP 1001 02/24/2026, 14:24:02 0x123...abc 📋 View" [ref=e48] [cursor=pointer]:
+ - cell "CABC1234...567890 📋" [ref=e49]:
+ - generic [ref=e50]:
+ - code [ref=e51]: CABC1234...567890
+ - button "📋" [ref=e52]
+ - cell "SWAP" [ref=e53]:
+ - generic [ref=e54]: SWAP
+ - cell "1001" [ref=e55]:
+ - button "1001" [ref=e56]
+ - cell "02/24/2026, 14:24:02" [ref=e57]
+ - cell "0x123...abc 📋" [ref=e58]:
+ - generic [ref=e59]:
+ - code [ref=e60]: 0x123...abc
+ - button "📋" [ref=e61]
+ - cell "View" [ref=e62]:
+ - button "View" [ref=e63]
+ - row "CABC1234...567890 📋 TRANSFER 1002 02/24/2026, 14:24:02 0x456...def 📋 View" [ref=e64] [cursor=pointer]:
+ - cell "CABC1234...567890 📋" [ref=e65]:
+ - generic [ref=e66]:
+ - code [ref=e67]: CABC1234...567890
+ - button "📋" [ref=e68]
+ - cell "TRANSFER" [ref=e69]:
+ - generic [ref=e70]: TRANSFER
+ - cell "1002" [ref=e71]:
+ - button "1002" [ref=e72]
+ - cell "02/24/2026, 14:24:02" [ref=e73]
+ - cell "0x456...def 📋" [ref=e74]:
+ - generic [ref=e75]:
+ - code [ref=e76]: 0x456...def
+ - button "📋" [ref=e77]
+ - cell "View" [ref=e78]:
+ - button "View" [ref=e79]
+ - generic [ref=e80]:
+ - button "◄◄" [disabled] [ref=e81]
+ - button "◄ Previous" [disabled] [ref=e82]
+ - generic [ref=e83]: Page 1
+ - generic [ref=e84]: Showing 1-2 of 2+
+ - button "Next ►" [disabled] [ref=e85]
+ - button "►►" [disabled] [ref=e86]
+ - button "Open Next.js Dev Tools" [ref=e92] [cursor=pointer]:
+ - img [ref=e93]
+ - alert [ref=e97]
+```
\ No newline at end of file
diff --git a/soroscan-frontend/playwright-report/data/72b4015ff3d646ea609c9e6afdca77c349b36c0f.png b/soroscan-frontend/playwright-report/data/72b4015ff3d646ea609c9e6afdca77c349b36c0f.png
new file mode 100644
index 000000000..ff51b9443
Binary files /dev/null and b/soroscan-frontend/playwright-report/data/72b4015ff3d646ea609c9e6afdca77c349b36c0f.png differ
diff --git a/soroscan-frontend/playwright-report/data/7af459e76ce80cd6c21c4e642499bec3287e9f54.md b/soroscan-frontend/playwright-report/data/7af459e76ce80cd6c21c4e642499bec3287e9f54.md
new file mode 100644
index 000000000..6daa5f6c2
--- /dev/null
+++ b/soroscan-frontend/playwright-report/data/7af459e76ce80cd6c21c4e642499bec3287e9f54.md
@@ -0,0 +1,65 @@
+# Page snapshot
+
+```yaml
+- generic [ref=e1]:
+ - main [ref=e3]:
+ - generic [ref=e4]:
+ - paragraph [ref=e5]: SoroScan
+ - heading "Event Explorer Dashboard" [level=1] [ref=e6]
+ - paragraph [ref=e7]: Browse, filter, and analyze contract events in real-time
+ - region "Event filters" [ref=e8]:
+ - generic [ref=e9]:
+ - heading "Filters" [level=2] [ref=e10]
+ - generic [ref=e11]:
+ - generic [ref=e12]:
+ - generic [ref=e13]: Contract
+ - combobox "Contract" [ref=e14]:
+ - option "All Contracts"
+ - option "Test Token" [selected]
+ - option "Liquidity Pool"
+ - generic [ref=e15]:
+ - generic [ref=e16]: Event Type
+ - combobox "Event Type" [ref=e17]:
+ - option "All Types" [selected]
+ - generic [ref=e18]:
+ - generic [ref=e19]: From
+ - textbox "From" [ref=e20]
+ - generic [ref=e21]:
+ - generic [ref=e22]: To
+ - textbox "To" [ref=e23]
+ - generic [ref=e25]:
+ - generic [ref=e26]: Search
+ - textbox "Search" [ref=e27]:
+ - /placeholder: Search events...
+ - generic [ref=e28]:
+ - button "Apply Filters" [ref=e29] [cursor=pointer]
+ - button "Clear" [ref=e30] [cursor=pointer]
+ - button "Export CSV" [active] [ref=e31] [cursor=pointer]
+ - button "Export JSON" [ref=e32] [cursor=pointer]
+ - region "Events table" [ref=e33]:
+ - generic [ref=e34]:
+ - heading "Contract Events" [level=2] [ref=e35]
+ - paragraph [ref=e36]: Showing 1-0 of 0+
+ - table [ref=e38]:
+ - rowgroup [ref=e39]:
+ - row "Contract Type Ledger Time Transaction Actions" [ref=e40]:
+ - columnheader "Contract" [ref=e41]
+ - columnheader "Type" [ref=e42]
+ - columnheader "Ledger" [ref=e43]
+ - columnheader "Time" [ref=e44]
+ - columnheader "Transaction" [ref=e45]
+ - columnheader "Actions" [ref=e46]
+ - rowgroup [ref=e47]:
+ - row "No events found. Select a contract and adjust filters to view events." [ref=e48]:
+ - cell "No events found. Select a contract and adjust filters to view events." [ref=e49]
+ - generic [ref=e50]:
+ - button "◄◄" [disabled] [ref=e51]
+ - button "◄ Previous" [disabled] [ref=e52]
+ - generic [ref=e53]: Page 1
+ - generic [ref=e54]: Showing 1-0 of 0+
+ - button "Next ►" [disabled] [ref=e55]
+ - button "►►" [disabled] [ref=e56]
+ - button "Open Next.js Dev Tools" [ref=e62] [cursor=pointer]:
+ - img [ref=e63]
+ - alert [ref=e67]
+```
\ No newline at end of file
diff --git a/soroscan-frontend/playwright-report/data/7cc76a1b2bbbbdb1db5a81f239ff7bcdc11312e4.md b/soroscan-frontend/playwright-report/data/7cc76a1b2bbbbdb1db5a81f239ff7bcdc11312e4.md
new file mode 100644
index 000000000..1819fefd8
--- /dev/null
+++ b/soroscan-frontend/playwright-report/data/7cc76a1b2bbbbdb1db5a81f239ff7bcdc11312e4.md
@@ -0,0 +1,99 @@
+# Page snapshot
+
+```yaml
+- generic [ref=e1]:
+ - main [ref=e3]:
+ - generic [ref=e4]:
+ - paragraph [ref=e5]: SoroScan
+ - heading "Event Explorer Dashboard" [level=1] [ref=e6]
+ - paragraph [ref=e7]: Browse, filter, and analyze contract events in real-time
+ - region "Event filters" [ref=e8]:
+ - generic [ref=e9]:
+ - heading "Filters" [level=2] [ref=e10]
+ - generic [ref=e11]:
+ - generic [ref=e12]:
+ - generic [ref=e13]: Contract
+ - combobox "Contract" [ref=e14]:
+ - option "All Contracts"
+ - option "Test Token" [selected]
+ - option "Liquidity Pool"
+ - generic [ref=e15]:
+ - generic [ref=e16]: Event Type
+ - combobox "Event Type" [ref=e17]:
+ - option "All Types" [selected]
+ - option "SWAP"
+ - option "MINT"
+ - option "BURN"
+ - option "TRANSFER"
+ - generic [ref=e18]:
+ - generic [ref=e19]: From
+ - textbox "From" [ref=e20]
+ - generic [ref=e21]:
+ - generic [ref=e22]: To
+ - textbox "To" [ref=e23]
+ - generic [ref=e25]:
+ - generic [ref=e26]: Search
+ - textbox "Search" [ref=e27]:
+ - /placeholder: Search events...
+ - generic [ref=e28]:
+ - button "Apply Filters" [active] [ref=e29] [cursor=pointer]
+ - button "Clear" [ref=e30] [cursor=pointer]
+ - button "Export CSV" [ref=e31] [cursor=pointer]
+ - button "Export JSON" [ref=e32] [cursor=pointer]
+ - region "Events table" [ref=e33]:
+ - generic [ref=e34]:
+ - heading "Contract Events" [level=2] [ref=e35]
+ - paragraph [ref=e36]: Showing 1-2 of 2+
+ - table [ref=e38]:
+ - rowgroup [ref=e39]:
+ - row "Contract Type Ledger Time Transaction Actions" [ref=e40]:
+ - columnheader "Contract" [ref=e41]
+ - columnheader "Type" [ref=e42]
+ - columnheader "Ledger" [ref=e43]
+ - columnheader "Time" [ref=e44]
+ - columnheader "Transaction" [ref=e45]
+ - columnheader "Actions" [ref=e46]
+ - rowgroup [ref=e47]:
+ - row "CABC1234...567890 📋 SWAP 1001 02/24/2026, 14:22:49 0x123...abc 📋 View" [ref=e48] [cursor=pointer]:
+ - cell "CABC1234...567890 📋" [ref=e49]:
+ - generic [ref=e50]:
+ - code [ref=e51]: CABC1234...567890
+ - button "📋" [ref=e52]
+ - cell "SWAP" [ref=e53]:
+ - generic [ref=e54]: SWAP
+ - cell "1001" [ref=e55]:
+ - button "1001" [ref=e56]
+ - cell "02/24/2026, 14:22:49" [ref=e57]
+ - cell "0x123...abc 📋" [ref=e58]:
+ - generic [ref=e59]:
+ - code [ref=e60]: 0x123...abc
+ - button "📋" [ref=e61]
+ - cell "View" [ref=e62]:
+ - button "View" [ref=e63]
+ - row "CABC1234...567890 📋 TRANSFER 1002 02/24/2026, 14:22:49 0x456...def 📋 View" [ref=e64] [cursor=pointer]:
+ - cell "CABC1234...567890 📋" [ref=e65]:
+ - generic [ref=e66]:
+ - code [ref=e67]: CABC1234...567890
+ - button "📋" [ref=e68]
+ - cell "TRANSFER" [ref=e69]:
+ - generic [ref=e70]: TRANSFER
+ - cell "1002" [ref=e71]:
+ - button "1002" [ref=e72]
+ - cell "02/24/2026, 14:22:49" [ref=e73]
+ - cell "0x456...def 📋" [ref=e74]:
+ - generic [ref=e75]:
+ - code [ref=e76]: 0x456...def
+ - button "📋" [ref=e77]
+ - cell "View" [ref=e78]:
+ - button "View" [ref=e79]
+ - generic [ref=e80]:
+ - button "◄◄" [disabled] [ref=e81]
+ - button "◄ Previous" [disabled] [ref=e82]
+ - generic [ref=e83]: Page 1
+ - generic [ref=e84]: Showing 1-2 of 2+
+ - button "Next ►" [disabled] [ref=e85]
+ - button "►►" [disabled] [ref=e86]
+ - button "Open Next.js Dev Tools" [ref=e92] [cursor=pointer]:
+ - img [ref=e93]
+ - alert [ref=e96]
+```
\ No newline at end of file
diff --git a/soroscan-frontend/playwright-report/data/82fa6da650dbd0755676456ce4ff80530f439d08.png b/soroscan-frontend/playwright-report/data/82fa6da650dbd0755676456ce4ff80530f439d08.png
new file mode 100644
index 000000000..ab15db16e
Binary files /dev/null and b/soroscan-frontend/playwright-report/data/82fa6da650dbd0755676456ce4ff80530f439d08.png differ
diff --git a/soroscan-frontend/playwright-report/data/8cee7f8cc016de1aaa873b19d00824e3985c742f.png b/soroscan-frontend/playwright-report/data/8cee7f8cc016de1aaa873b19d00824e3985c742f.png
new file mode 100644
index 000000000..de3753add
Binary files /dev/null and b/soroscan-frontend/playwright-report/data/8cee7f8cc016de1aaa873b19d00824e3985c742f.png differ
diff --git a/soroscan-frontend/playwright-report/data/9d6cff20373879008895ca019c503745030b2566.md b/soroscan-frontend/playwright-report/data/9d6cff20373879008895ca019c503745030b2566.md
new file mode 100644
index 000000000..de6d4a29c
--- /dev/null
+++ b/soroscan-frontend/playwright-report/data/9d6cff20373879008895ca019c503745030b2566.md
@@ -0,0 +1,65 @@
+# Page snapshot
+
+```yaml
+- generic [ref=e1]:
+ - main [ref=e3]:
+ - generic [ref=e4]:
+ - paragraph [ref=e5]: SoroScan
+ - heading "Event Explorer Dashboard" [level=1] [ref=e6]
+ - paragraph [ref=e7]: Browse, filter, and analyze contract events in real-time
+ - region "Event filters" [ref=e8]:
+ - generic [ref=e9]:
+ - heading "Filters" [level=2] [ref=e10]
+ - generic [ref=e11]:
+ - generic [ref=e12]:
+ - generic [ref=e13]: Contract
+ - combobox "Contract" [ref=e14]:
+ - option "All Contracts"
+ - option "Test Token" [selected]
+ - option "Liquidity Pool"
+ - generic [ref=e15]:
+ - generic [ref=e16]: Event Type
+ - combobox "Event Type" [ref=e17]:
+ - option "All Types" [selected]
+ - generic [ref=e18]:
+ - generic [ref=e19]: From
+ - textbox "From" [ref=e20]
+ - generic [ref=e21]:
+ - generic [ref=e22]: To
+ - textbox "To" [ref=e23]
+ - generic [ref=e25]:
+ - generic [ref=e26]: Search
+ - textbox "Search" [ref=e27]:
+ - /placeholder: Search events...
+ - generic [ref=e28]:
+ - button "Apply Filters" [ref=e29] [cursor=pointer]
+ - button "Clear" [ref=e30] [cursor=pointer]
+ - button "Export CSV" [active] [ref=e31] [cursor=pointer]
+ - button "Export JSON" [ref=e32] [cursor=pointer]
+ - region "Events table" [ref=e33]:
+ - generic [ref=e34]:
+ - heading "Contract Events" [level=2] [ref=e35]
+ - paragraph [ref=e36]: Showing 1-0 of 0+
+ - table [ref=e38]:
+ - rowgroup [ref=e39]:
+ - row "Contract Type Ledger Time Transaction Actions" [ref=e40]:
+ - columnheader "Contract" [ref=e41]
+ - columnheader "Type" [ref=e42]
+ - columnheader "Ledger" [ref=e43]
+ - columnheader "Time" [ref=e44]
+ - columnheader "Transaction" [ref=e45]
+ - columnheader "Actions" [ref=e46]
+ - rowgroup [ref=e47]:
+ - row "No events found. Select a contract and adjust filters to view events." [ref=e48]:
+ - cell "No events found. Select a contract and adjust filters to view events." [ref=e49]
+ - generic [ref=e50]:
+ - button "◄◄" [disabled] [ref=e51]
+ - button "◄ Previous" [disabled] [ref=e52]
+ - generic [ref=e53]: Page 1
+ - generic [ref=e54]: Showing 1-0 of 0+
+ - button "Next ►" [disabled] [ref=e55]
+ - button "►►" [disabled] [ref=e56]
+ - button "Open Next.js Dev Tools" [ref=e62] [cursor=pointer]:
+ - img [ref=e63]
+ - alert [ref=e66]
+```
\ No newline at end of file
diff --git a/soroscan-frontend/playwright-report/data/a10ead5e522c244a291b6293d8808e4f462252a2.png b/soroscan-frontend/playwright-report/data/a10ead5e522c244a291b6293d8808e4f462252a2.png
new file mode 100644
index 000000000..99afd93ad
Binary files /dev/null and b/soroscan-frontend/playwright-report/data/a10ead5e522c244a291b6293d8808e4f462252a2.png differ
diff --git a/soroscan-frontend/playwright-report/data/a5e469d8334ab3bdab515cd409e9f539adce417a.png b/soroscan-frontend/playwright-report/data/a5e469d8334ab3bdab515cd409e9f539adce417a.png
new file mode 100644
index 000000000..9b5f6d77d
Binary files /dev/null and b/soroscan-frontend/playwright-report/data/a5e469d8334ab3bdab515cd409e9f539adce417a.png differ
diff --git a/soroscan-frontend/playwright-report/data/c57d80646bec1d00f2d510aa0042029dc26171e0.md b/soroscan-frontend/playwright-report/data/c57d80646bec1d00f2d510aa0042029dc26171e0.md
new file mode 100644
index 000000000..0cde90259
--- /dev/null
+++ b/soroscan-frontend/playwright-report/data/c57d80646bec1d00f2d510aa0042029dc26171e0.md
@@ -0,0 +1,328 @@
+# Page snapshot
+
+```yaml
+- generic [active] [ref=e1]:
+ - generic [ref=e2]:
+ - navigation [ref=e3]:
+ - generic [ref=e4]:
+ - link "[SOROSCAN]" [ref=e5] [cursor=pointer]:
+ - /url: /
+ - generic [ref=e6]:
+ - link "DOCS" [ref=e7] [cursor=pointer]:
+ - /url: /docs
+ - link "FEATURES" [ref=e8] [cursor=pointer]:
+ - /url: /features
+ - link "API_DOCS" [ref=e9] [cursor=pointer]:
+ - /url: /api/docs/
+ - link "GITHUB" [ref=e10] [cursor=pointer]:
+ - /url: https://github.com/SoroScan/soroscan
+ - link "> GET_API_KEY" [ref=e12] [cursor=pointer]:
+ - /url: /api/docs/
+ - button "> GET_API_KEY" [ref=e13]:
+ - generic [ref=e14]:
+ - generic [ref=e15]: ">"
+ - text: GET_API_KEY
+ - main [ref=e16]:
+ - generic [ref=e17]:
+ - generic [ref=e18]:
+ - generic [ref=e19]: "[WEBHOOK_MANAGER]"
+ - heading "SUBSCRIPTIONS" [level=1] [ref=e20]
+ - paragraph [ref=e21]: 6 subscriptions configured
+ - button "> NEW_WEBHOOK" [ref=e22]:
+ - generic [ref=e23]:
+ - generic [ref=e24]: ">"
+ - img [ref=e25]
+ - text: NEW_WEBHOOK
+ - generic [ref=e26]:
+ - generic [ref=e27]:
+ - generic [ref=e28]: "6"
+ - generic [ref=e29]: TOTAL
+ - generic [ref=e30]:
+ - generic [ref=e31]:
+ - img [ref=e32]
+ - text: "4"
+ - generic [ref=e34]: ACTIVE
+ - generic [ref=e35]:
+ - generic [ref=e36]:
+ - img [ref=e37]
+ - text: "1"
+ - generic [ref=e39]: FAILED
+ - generic [ref=e40]:
+ - generic [ref=e41]: 80.7%
+ - generic [ref=e42]: AVG_SUCCESS
+ - generic [ref=e43]: "LAST_EVENT: 23/02/2026, 23:34:01"
+ - generic [ref=e45]:
+ - heading "[WEBHOOK_LIST]" [level=2] [ref=e47]
+ - table [ref=e51]:
+ - rowgroup [ref=e52]:
+ - row "STATUS ENDPOINT_URL EVENT_TYPES SUCCESS LAST_DELIVERY ACTIONS" [ref=e53]:
+ - columnheader "STATUS" [ref=e54] [cursor=pointer]:
+ - generic [ref=e55]:
+ - text: STATUS
+ - img [ref=e56]
+ - columnheader "ENDPOINT_URL" [ref=e58] [cursor=pointer]:
+ - generic [ref=e59]:
+ - text: ENDPOINT_URL
+ - img [ref=e60]
+ - columnheader "EVENT_TYPES" [ref=e62]
+ - columnheader "SUCCESS" [ref=e63] [cursor=pointer]:
+ - generic [ref=e64]:
+ - text: SUCCESS
+ - img [ref=e65]
+ - columnheader "LAST_DELIVERY" [ref=e67] [cursor=pointer]:
+ - generic [ref=e68]:
+ - text: LAST_DELIVERY
+ - img [ref=e69]
+ - columnheader "ACTIONS" [ref=e71]
+ - rowgroup [ref=e72]:
+ - 'row "ACTIVE https://api.myapp.io/hooks/soroban CONTRACT: CABC...9X4Z SWAP_COMPLETE LIQUIDITY_ADD 98.7% 23/02/2026, 23:34 HTTP 200 > DETAIL" [ref=e73]':
+ - cell "ACTIVE" [ref=e74]:
+ - generic [ref=e75]: ACTIVE
+ - 'cell "https://api.myapp.io/hooks/soroban CONTRACT: CABC...9X4Z" [ref=e77]':
+ - generic [ref=e78]:
+ - link "https://api.myapp.io/hooks/soroban" [ref=e79] [cursor=pointer]:
+ - /url: /webhooks/wh_001
+ - generic [ref=e80]: "CONTRACT: CABC...9X4Z"
+ - cell "SWAP_COMPLETE LIQUIDITY_ADD" [ref=e81]:
+ - generic [ref=e82]:
+ - generic [ref=e83]: SWAP_COMPLETE
+ - generic [ref=e84]: LIQUIDITY_ADD
+ - cell "98.7%" [ref=e85]:
+ - generic [ref=e89]: 98.7%
+ - cell "23/02/2026, 23:34 HTTP 200" [ref=e90]:
+ - text: 23/02/2026, 23:34
+ - generic [ref=e91]: HTTP 200
+ - cell "> DETAIL" [ref=e92]:
+ - generic [ref=e93]:
+ - link "> DETAIL" [ref=e94] [cursor=pointer]:
+ - /url: /webhooks/wh_001
+ - button "> DETAIL" [ref=e95]:
+ - generic [ref=e96]:
+ - generic [ref=e97]: ">"
+ - text: DETAIL
+ - button "Test webhook" [ref=e98]:
+ - img [ref=e99]
+ - button "Delete webhook" [ref=e101]:
+ - img [ref=e102]
+ - row "ACTIVE https://realtime.indexer.finance/soroscan-events ORACLE_UPDATE STAKING_LOCK SWAP_COMPLETE 99.1% 23/02/2026, 23:33 HTTP 200 > DETAIL" [ref=e105]:
+ - cell "ACTIVE" [ref=e106]:
+ - generic [ref=e107]: ACTIVE
+ - cell "https://realtime.indexer.finance/soroscan-events" [ref=e109]:
+ - link "https://realtime.indexer.finance/soroscan-events" [ref=e111] [cursor=pointer]:
+ - /url: /webhooks/wh_005
+ - cell "ORACLE_UPDATE STAKING_LOCK SWAP_COMPLETE" [ref=e112]:
+ - generic [ref=e113]:
+ - generic [ref=e114]: ORACLE_UPDATE
+ - generic [ref=e115]: STAKING_LOCK
+ - generic [ref=e116]: SWAP_COMPLETE
+ - cell "99.1%" [ref=e117]:
+ - generic [ref=e121]: 99.1%
+ - cell "23/02/2026, 23:33 HTTP 200" [ref=e122]:
+ - text: 23/02/2026, 23:33
+ - generic [ref=e123]: HTTP 200
+ - cell "> DETAIL" [ref=e124]:
+ - generic [ref=e125]:
+ - link "> DETAIL" [ref=e126] [cursor=pointer]:
+ - /url: /webhooks/wh_005
+ - button "> DETAIL" [ref=e127]:
+ - generic [ref=e128]:
+ - generic [ref=e129]: ">"
+ - text: DETAIL
+ - button "Test webhook" [ref=e130]:
+ - img [ref=e131]
+ - button "Delete webhook" [ref=e133]:
+ - img [ref=e134]
+ - row "ACTIVE https://webhook.site/abc123def456 ALL_EVENTS 100.0% 23/02/2026, 23:31 HTTP 200 > DETAIL" [ref=e137]:
+ - cell "ACTIVE" [ref=e138]:
+ - generic [ref=e139]: ACTIVE
+ - cell "https://webhook.site/abc123def456" [ref=e141]:
+ - link "https://webhook.site/abc123def456" [ref=e143] [cursor=pointer]:
+ - /url: /webhooks/wh_002
+ - cell "ALL_EVENTS" [ref=e144]:
+ - generic [ref=e146]: ALL_EVENTS
+ - cell "100.0%" [ref=e147]:
+ - generic [ref=e151]: 100.0%
+ - cell "23/02/2026, 23:31 HTTP 200" [ref=e152]:
+ - text: 23/02/2026, 23:31
+ - generic [ref=e153]: HTTP 200
+ - cell "> DETAIL" [ref=e154]:
+ - generic [ref=e155]:
+ - link "> DETAIL" [ref=e156] [cursor=pointer]:
+ - /url: /webhooks/wh_002
+ - button "> DETAIL" [ref=e157]:
+ - generic [ref=e158]:
+ - generic [ref=e159]: ">"
+ - text: DETAIL
+ - button "Test webhook" [ref=e160]:
+ - img [ref=e161]
+ - button "Delete webhook" [ref=e163]:
+ - img [ref=e164]
+ - row "FAILED https://hooks.internal.corp/blockchain-events GOV_PROPOSAL 12.1% 23/02/2026, 21:55 HTTP 404 > DETAIL" [ref=e167]:
+ - cell "FAILED" [ref=e168]:
+ - generic [ref=e169]: FAILED
+ - cell "https://hooks.internal.corp/blockchain-events" [ref=e171]:
+ - link "https://hooks.internal.corp/blockchain-events" [ref=e173] [cursor=pointer]:
+ - /url: /webhooks/wh_004
+ - cell "GOV_PROPOSAL" [ref=e174]:
+ - generic [ref=e176]: GOV_PROPOSAL
+ - cell "12.1%" [ref=e177]:
+ - generic [ref=e181]: 12.1%
+ - cell "23/02/2026, 21:55 HTTP 404" [ref=e182]:
+ - text: 23/02/2026, 21:55
+ - generic [ref=e183]: HTTP 404
+ - cell "> DETAIL" [ref=e184]:
+ - generic [ref=e185]:
+ - link "> DETAIL" [ref=e186] [cursor=pointer]:
+ - /url: /webhooks/wh_004
+ - button "> DETAIL" [ref=e187]:
+ - generic [ref=e188]:
+ - generic [ref=e189]: ">"
+ - text: DETAIL
+ - button "Test webhook" [ref=e190]:
+ - img [ref=e191]
+ - button "Delete webhook" [ref=e193]:
+ - img [ref=e194]
+ - 'row "SUSPENDED https://events.defiprotocol.org/soroscan CONTRACT: CGHI...F7K1 VAULT_DEPOSIT YIELD_CLAIMED 74.2% 21/02/2026, 09:10 HTTP 503 > DETAIL" [ref=e197]':
+ - cell "SUSPENDED" [ref=e198]:
+ - generic [ref=e199]: SUSPENDED
+ - 'cell "https://events.defiprotocol.org/soroscan CONTRACT: CGHI...F7K1" [ref=e201]':
+ - generic [ref=e202]:
+ - link "https://events.defiprotocol.org/soroscan" [ref=e203] [cursor=pointer]:
+ - /url: /webhooks/wh_003
+ - generic [ref=e204]: "CONTRACT: CGHI...F7K1"
+ - cell "VAULT_DEPOSIT YIELD_CLAIMED" [ref=e205]:
+ - generic [ref=e206]:
+ - generic [ref=e207]: VAULT_DEPOSIT
+ - generic [ref=e208]: YIELD_CLAIMED
+ - cell "74.2%" [ref=e209]:
+ - generic [ref=e213]: 74.2%
+ - cell "21/02/2026, 09:10 HTTP 503" [ref=e214]:
+ - text: 21/02/2026, 09:10
+ - generic [ref=e215]: HTTP 503
+ - cell "> DETAIL" [ref=e216]:
+ - generic [ref=e217]:
+ - link "> DETAIL" [ref=e218] [cursor=pointer]:
+ - /url: /webhooks/wh_003
+ - button "> DETAIL" [ref=e219]:
+ - generic [ref=e220]:
+ - generic [ref=e221]: ">"
+ - text: DETAIL
+ - button "Test webhook" [ref=e222]:
+ - img [ref=e223]
+ - button "Delete webhook" [ref=e225]:
+ - img [ref=e226]
+ - row "ACTIVE https://example.com/webhook ALL_EVENTS 100.0% — > DETAIL" [ref=e229]:
+ - cell "ACTIVE" [ref=e230]:
+ - generic [ref=e231]: ACTIVE
+ - cell "https://example.com/webhook" [ref=e233]:
+ - link "https://example.com/webhook" [ref=e235] [cursor=pointer]:
+ - /url: /webhooks/wh_ejsu7
+ - cell "ALL_EVENTS" [ref=e236]:
+ - generic [ref=e238]: ALL_EVENTS
+ - cell "100.0%" [ref=e239]:
+ - generic [ref=e243]: 100.0%
+ - cell "—" [ref=e244]
+ - cell "> DETAIL" [ref=e245]:
+ - generic [ref=e246]:
+ - link "> DETAIL" [ref=e247] [cursor=pointer]:
+ - /url: /webhooks/wh_ejsu7
+ - button "> DETAIL" [ref=e248]:
+ - generic [ref=e249]:
+ - generic [ref=e250]: ">"
+ - text: DETAIL
+ - button "Test webhook" [disabled] [ref=e251]:
+ - img [ref=e252]
+ - button "Delete webhook" [ref=e254]:
+ - img [ref=e255]
+ - generic [ref=e258]:
+ - generic [ref=e259]:
+ - generic [ref=e260]: SYSTEM_OVERRIDE_ACTIVE
+ - generic [ref=e261]: "AUTH_MODE: DEV_OPEN"
+ - heading "READY_TO_UPLINK?" [level=2] [ref=e262]
+ - paragraph [ref=e263]: Join the decentralised indexing network and fuel your Soroban dApps with high-fidelity event data — free during open beta.
+ - generic [ref=e264]:
+ - link "> GET_API_KEY" [ref=e265] [cursor=pointer]:
+ - /url: /api/docs/
+ - button "> GET_API_KEY" [ref=e266]:
+ - generic [ref=e267]:
+ - generic [ref=e268]: ">"
+ - text: GET_API_KEY
+ - link "> READ_DOCS" [ref=e269] [cursor=pointer]:
+ - /url: /docs
+ - button "> READ_DOCS" [ref=e270]:
+ - generic [ref=e271]:
+ - generic [ref=e272]: ">"
+ - text: READ_DOCS
+ - contentinfo [ref=e273]:
+ - generic [ref=e274]:
+ - generic [ref=e275]:
+ - link "[SOROSCAN]" [ref=e276] [cursor=pointer]:
+ - /url: /
+ - paragraph [ref=e277]: The Graph for Soroban. Real-time event indexing for the Stellar ecosystem.
+ - link "GitHub" [ref=e278] [cursor=pointer]:
+ - /url: https://github.com/SoroScan/soroscan
+ - img [ref=e279]
+ - text: GitHub
+ - generic [ref=e282]:
+ - heading "PRODUCT" [level=3] [ref=e283]
+ - list [ref=e284]:
+ - listitem [ref=e285]:
+ - link "Home" [ref=e286] [cursor=pointer]:
+ - /url: /
+ - listitem [ref=e287]:
+ - link "Features" [ref=e288] [cursor=pointer]:
+ - /url: /features
+ - listitem [ref=e289]:
+ - link "Dashboard" [ref=e290] [cursor=pointer]:
+ - /url: /dashboard
+ - listitem [ref=e291]:
+ - link "Gallery" [ref=e292] [cursor=pointer]:
+ - /url: /gallery
+ - generic [ref=e293]:
+ - heading "DEVELOPERS" [level=3] [ref=e294]
+ - list [ref=e295]:
+ - listitem [ref=e296]:
+ - link "Documentation" [ref=e297] [cursor=pointer]:
+ - /url: /docs
+ - listitem [ref=e298]:
+ - link "API Docs (Swagger)" [ref=e299] [cursor=pointer]:
+ - /url: /api/docs/
+ - listitem [ref=e300]:
+ - link "API Docs (ReDoc)" [ref=e301] [cursor=pointer]:
+ - /url: /api/redoc/
+ - listitem [ref=e302]:
+ - link "SDK — Python" [ref=e303] [cursor=pointer]:
+ - /url: https://github.com/SoroScan/soroscan
+ - listitem [ref=e304]:
+ - link "SDK — TypeScript" [ref=e305] [cursor=pointer]:
+ - /url: https://github.com/SoroScan/soroscan
+ - generic [ref=e306]:
+ - heading "PROJECT" [level=3] [ref=e307]
+ - list [ref=e308]:
+ - listitem [ref=e309]:
+ - link "GitHub" [ref=e310] [cursor=pointer]:
+ - /url: https://github.com/SoroScan/soroscan
+ - listitem [ref=e311]:
+ - link "Contributing" [ref=e312] [cursor=pointer]:
+ - /url: https://github.com/SoroScan/soroscan/blob/main/CONTRIBUTING.md
+ - listitem [ref=e313]:
+ - link "Stellar Network" [ref=e314] [cursor=pointer]:
+ - /url: https://stellar.org
+ - listitem [ref=e315]:
+ - link "Soroban Docs" [ref=e316] [cursor=pointer]:
+ - /url: https://soroban.stellar.org
+ - generic [ref=e317]:
+ - generic [ref=e318]:
+ - generic [ref=e319]: © 2026 SOROSCAN_INDEXER_SERVICES
+ - link "TERMS_OF_SERVICE" [ref=e320] [cursor=pointer]:
+ - /url: "#"
+ - link "PRIVACY_POLICY" [ref=e321] [cursor=pointer]:
+ - /url: "#"
+ - generic [ref=e322]:
+ - generic [ref=e323]: "STELLAR_MAINNET_UPLINK: ONLINE"
+ - generic [ref=e325]: "LATENCY: 42MS"
+ - generic [ref=e326]: ✓WEBHOOK_CREATED — subscription is now active
+ - button "Open Next.js Dev Tools" [ref=e332] [cursor=pointer]:
+ - img [ref=e333]
+ - alert [ref=e336]
+```
\ No newline at end of file
diff --git a/soroscan-frontend/playwright-report/data/d1674060622d6982aef68d159f6e636c0b049fe7.md b/soroscan-frontend/playwright-report/data/d1674060622d6982aef68d159f6e636c0b049fe7.md
new file mode 100644
index 000000000..20565060c
--- /dev/null
+++ b/soroscan-frontend/playwright-report/data/d1674060622d6982aef68d159f6e636c0b049fe7.md
@@ -0,0 +1,328 @@
+# Page snapshot
+
+```yaml
+- generic [active] [ref=e1]:
+ - generic [ref=e2]:
+ - navigation [ref=e3]:
+ - generic [ref=e4]:
+ - link "[SOROSCAN]" [ref=e5] [cursor=pointer]:
+ - /url: /
+ - generic [ref=e6]:
+ - link "DOCS" [ref=e7] [cursor=pointer]:
+ - /url: /docs
+ - link "FEATURES" [ref=e8] [cursor=pointer]:
+ - /url: /features
+ - link "API_DOCS" [ref=e9] [cursor=pointer]:
+ - /url: /api/docs/
+ - link "GITHUB" [ref=e10] [cursor=pointer]:
+ - /url: https://github.com/SoroScan/soroscan
+ - link "> GET_API_KEY" [ref=e12] [cursor=pointer]:
+ - /url: /api/docs/
+ - button "> GET_API_KEY" [ref=e13]:
+ - generic [ref=e14]:
+ - generic [ref=e15]: ">"
+ - text: GET_API_KEY
+ - main [ref=e16]:
+ - generic [ref=e17]:
+ - generic [ref=e18]:
+ - generic [ref=e19]: "[WEBHOOK_MANAGER]"
+ - heading "SUBSCRIPTIONS" [level=1] [ref=e20]
+ - paragraph [ref=e21]: 6 subscriptions configured
+ - button "> NEW_WEBHOOK" [ref=e22]:
+ - generic [ref=e23]:
+ - generic [ref=e24]: ">"
+ - img [ref=e25]
+ - text: NEW_WEBHOOK
+ - generic [ref=e28]:
+ - generic [ref=e29]:
+ - generic [ref=e30]: "6"
+ - generic [ref=e31]: TOTAL
+ - generic [ref=e32]:
+ - generic [ref=e33]:
+ - img [ref=e34]
+ - text: "4"
+ - generic [ref=e36]: ACTIVE
+ - generic [ref=e37]:
+ - generic [ref=e38]:
+ - img [ref=e39]
+ - text: "1"
+ - generic [ref=e43]: FAILED
+ - generic [ref=e44]:
+ - generic [ref=e45]: 80.7%
+ - generic [ref=e46]: AVG_SUCCESS
+ - generic [ref=e47]: "LAST_EVENT: 23/02/2026, 23:34:01"
+ - generic [ref=e49]:
+ - heading "[WEBHOOK_LIST]" [level=2] [ref=e51]
+ - table [ref=e55]:
+ - rowgroup [ref=e56]:
+ - row "STATUS ENDPOINT_URL EVENT_TYPES SUCCESS LAST_DELIVERY ACTIONS" [ref=e57]:
+ - columnheader "STATUS" [ref=e58] [cursor=pointer]:
+ - generic [ref=e59]:
+ - text: STATUS
+ - img [ref=e60]
+ - columnheader "ENDPOINT_URL" [ref=e62] [cursor=pointer]:
+ - generic [ref=e63]:
+ - text: ENDPOINT_URL
+ - img [ref=e64]
+ - columnheader "EVENT_TYPES" [ref=e66]
+ - columnheader "SUCCESS" [ref=e67] [cursor=pointer]:
+ - generic [ref=e68]:
+ - text: SUCCESS
+ - img [ref=e69]
+ - columnheader "LAST_DELIVERY" [ref=e71] [cursor=pointer]:
+ - generic [ref=e72]:
+ - text: LAST_DELIVERY
+ - img [ref=e73]
+ - columnheader "ACTIONS" [ref=e75]
+ - rowgroup [ref=e76]:
+ - 'row "ACTIVE https://api.myapp.io/hooks/soroban CONTRACT: CABC...9X4Z SWAP_COMPLETE LIQUIDITY_ADD 98.7% 23/02/2026, 23:34 HTTP 200 > DETAIL" [ref=e77]':
+ - cell "ACTIVE" [ref=e78]:
+ - generic [ref=e79]: ACTIVE
+ - 'cell "https://api.myapp.io/hooks/soroban CONTRACT: CABC...9X4Z" [ref=e81]':
+ - generic [ref=e82]:
+ - link "https://api.myapp.io/hooks/soroban" [ref=e83] [cursor=pointer]:
+ - /url: /webhooks/wh_001
+ - generic [ref=e84]: "CONTRACT: CABC...9X4Z"
+ - cell "SWAP_COMPLETE LIQUIDITY_ADD" [ref=e85]:
+ - generic [ref=e86]:
+ - generic [ref=e87]: SWAP_COMPLETE
+ - generic [ref=e88]: LIQUIDITY_ADD
+ - cell "98.7%" [ref=e89]:
+ - generic [ref=e93]: 98.7%
+ - cell "23/02/2026, 23:34 HTTP 200" [ref=e94]:
+ - text: 23/02/2026, 23:34
+ - generic [ref=e95]: HTTP 200
+ - cell "> DETAIL" [ref=e96]:
+ - generic [ref=e97]:
+ - link "> DETAIL" [ref=e98] [cursor=pointer]:
+ - /url: /webhooks/wh_001
+ - button "> DETAIL" [ref=e99]:
+ - generic [ref=e100]:
+ - generic [ref=e101]: ">"
+ - text: DETAIL
+ - button "Test webhook" [ref=e102]:
+ - img [ref=e103]
+ - button "Delete webhook" [ref=e107]:
+ - img [ref=e108]
+ - row "ACTIVE https://realtime.indexer.finance/soroscan-events ORACLE_UPDATE STAKING_LOCK SWAP_COMPLETE 99.1% 23/02/2026, 23:33 HTTP 200 > DETAIL" [ref=e114]:
+ - cell "ACTIVE" [ref=e115]:
+ - generic [ref=e116]: ACTIVE
+ - cell "https://realtime.indexer.finance/soroscan-events" [ref=e118]:
+ - link "https://realtime.indexer.finance/soroscan-events" [ref=e120] [cursor=pointer]:
+ - /url: /webhooks/wh_005
+ - cell "ORACLE_UPDATE STAKING_LOCK SWAP_COMPLETE" [ref=e121]:
+ - generic [ref=e122]:
+ - generic [ref=e123]: ORACLE_UPDATE
+ - generic [ref=e124]: STAKING_LOCK
+ - generic [ref=e125]: SWAP_COMPLETE
+ - cell "99.1%" [ref=e126]:
+ - generic [ref=e130]: 99.1%
+ - cell "23/02/2026, 23:33 HTTP 200" [ref=e131]:
+ - text: 23/02/2026, 23:33
+ - generic [ref=e132]: HTTP 200
+ - cell "> DETAIL" [ref=e133]:
+ - generic [ref=e134]:
+ - link "> DETAIL" [ref=e135] [cursor=pointer]:
+ - /url: /webhooks/wh_005
+ - button "> DETAIL" [ref=e136]:
+ - generic [ref=e137]:
+ - generic [ref=e138]: ">"
+ - text: DETAIL
+ - button "Test webhook" [ref=e139]:
+ - img [ref=e140]
+ - button "Delete webhook" [ref=e144]:
+ - img [ref=e145]
+ - row "ACTIVE https://webhook.site/abc123def456 ALL_EVENTS 100.0% 23/02/2026, 23:31 HTTP 200 > DETAIL" [ref=e151]:
+ - cell "ACTIVE" [ref=e152]:
+ - generic [ref=e153]: ACTIVE
+ - cell "https://webhook.site/abc123def456" [ref=e155]:
+ - link "https://webhook.site/abc123def456" [ref=e157] [cursor=pointer]:
+ - /url: /webhooks/wh_002
+ - cell "ALL_EVENTS" [ref=e158]:
+ - generic [ref=e160]: ALL_EVENTS
+ - cell "100.0%" [ref=e161]:
+ - generic [ref=e165]: 100.0%
+ - cell "23/02/2026, 23:31 HTTP 200" [ref=e166]:
+ - text: 23/02/2026, 23:31
+ - generic [ref=e167]: HTTP 200
+ - cell "> DETAIL" [ref=e168]:
+ - generic [ref=e169]:
+ - link "> DETAIL" [ref=e170] [cursor=pointer]:
+ - /url: /webhooks/wh_002
+ - button "> DETAIL" [ref=e171]:
+ - generic [ref=e172]:
+ - generic [ref=e173]: ">"
+ - text: DETAIL
+ - button "Test webhook" [ref=e174]:
+ - img [ref=e175]
+ - button "Delete webhook" [ref=e179]:
+ - img [ref=e180]
+ - row "FAILED https://hooks.internal.corp/blockchain-events GOV_PROPOSAL 12.1% 23/02/2026, 21:55 HTTP 404 > DETAIL" [ref=e186]:
+ - cell "FAILED" [ref=e187]:
+ - generic [ref=e188]: FAILED
+ - cell "https://hooks.internal.corp/blockchain-events" [ref=e190]:
+ - link "https://hooks.internal.corp/blockchain-events" [ref=e192] [cursor=pointer]:
+ - /url: /webhooks/wh_004
+ - cell "GOV_PROPOSAL" [ref=e193]:
+ - generic [ref=e195]: GOV_PROPOSAL
+ - cell "12.1%" [ref=e196]:
+ - generic [ref=e200]: 12.1%
+ - cell "23/02/2026, 21:55 HTTP 404" [ref=e201]:
+ - text: 23/02/2026, 21:55
+ - generic [ref=e202]: HTTP 404
+ - cell "> DETAIL" [ref=e203]:
+ - generic [ref=e204]:
+ - link "> DETAIL" [ref=e205] [cursor=pointer]:
+ - /url: /webhooks/wh_004
+ - button "> DETAIL" [ref=e206]:
+ - generic [ref=e207]:
+ - generic [ref=e208]: ">"
+ - text: DETAIL
+ - button "Test webhook" [ref=e209]:
+ - img [ref=e210]
+ - button "Delete webhook" [ref=e214]:
+ - img [ref=e215]
+ - 'row "SUSPENDED https://events.defiprotocol.org/soroscan CONTRACT: CGHI...F7K1 VAULT_DEPOSIT YIELD_CLAIMED 74.2% 21/02/2026, 09:10 HTTP 503 > DETAIL" [ref=e221]':
+ - cell "SUSPENDED" [ref=e222]:
+ - generic [ref=e223]: SUSPENDED
+ - 'cell "https://events.defiprotocol.org/soroscan CONTRACT: CGHI...F7K1" [ref=e225]':
+ - generic [ref=e226]:
+ - link "https://events.defiprotocol.org/soroscan" [ref=e227] [cursor=pointer]:
+ - /url: /webhooks/wh_003
+ - generic [ref=e228]: "CONTRACT: CGHI...F7K1"
+ - cell "VAULT_DEPOSIT YIELD_CLAIMED" [ref=e229]:
+ - generic [ref=e230]:
+ - generic [ref=e231]: VAULT_DEPOSIT
+ - generic [ref=e232]: YIELD_CLAIMED
+ - cell "74.2%" [ref=e233]:
+ - generic [ref=e237]: 74.2%
+ - cell "21/02/2026, 09:10 HTTP 503" [ref=e238]:
+ - text: 21/02/2026, 09:10
+ - generic [ref=e239]: HTTP 503
+ - cell "> DETAIL" [ref=e240]:
+ - generic [ref=e241]:
+ - link "> DETAIL" [ref=e242] [cursor=pointer]:
+ - /url: /webhooks/wh_003
+ - button "> DETAIL" [ref=e243]:
+ - generic [ref=e244]:
+ - generic [ref=e245]: ">"
+ - text: DETAIL
+ - button "Test webhook" [ref=e246]:
+ - img [ref=e247]
+ - button "Delete webhook" [ref=e251]:
+ - img [ref=e252]
+ - row "ACTIVE https://example.com/webhook ALL_EVENTS 100.0% — > DETAIL" [ref=e258]:
+ - cell "ACTIVE" [ref=e259]:
+ - generic [ref=e260]: ACTIVE
+ - cell "https://example.com/webhook" [ref=e262]:
+ - link "https://example.com/webhook" [ref=e264] [cursor=pointer]:
+ - /url: /webhooks/wh_lksbp
+ - cell "ALL_EVENTS" [ref=e265]:
+ - generic [ref=e267]: ALL_EVENTS
+ - cell "100.0%" [ref=e268]:
+ - generic [ref=e272]: 100.0%
+ - cell "—" [ref=e273]
+ - cell "> DETAIL" [ref=e274]:
+ - generic [ref=e275]:
+ - link "> DETAIL" [ref=e276] [cursor=pointer]:
+ - /url: /webhooks/wh_lksbp
+ - button "> DETAIL" [ref=e277]:
+ - generic [ref=e278]:
+ - generic [ref=e279]: ">"
+ - text: DETAIL
+ - button "Test webhook" [disabled] [ref=e280]:
+ - img [ref=e281]
+ - button "Delete webhook" [ref=e285]:
+ - img [ref=e286]
+ - generic [ref=e292]:
+ - generic [ref=e293]:
+ - generic [ref=e294]: SYSTEM_OVERRIDE_ACTIVE
+ - generic [ref=e295]: "AUTH_MODE: DEV_OPEN"
+ - heading "READY_TO_UPLINK?" [level=2] [ref=e296]
+ - paragraph [ref=e297]: Join the decentralised indexing network and fuel your Soroban dApps with high-fidelity event data — free during open beta.
+ - generic [ref=e298]:
+ - link "> GET_API_KEY" [ref=e299] [cursor=pointer]:
+ - /url: /api/docs/
+ - button "> GET_API_KEY" [ref=e300]:
+ - generic [ref=e301]:
+ - generic [ref=e302]: ">"
+ - text: GET_API_KEY
+ - link "> READ_DOCS" [ref=e303] [cursor=pointer]:
+ - /url: /docs
+ - button "> READ_DOCS" [ref=e304]:
+ - generic [ref=e305]:
+ - generic [ref=e306]: ">"
+ - text: READ_DOCS
+ - contentinfo [ref=e307]:
+ - generic [ref=e308]:
+ - generic [ref=e309]:
+ - link "[SOROSCAN]" [ref=e310] [cursor=pointer]:
+ - /url: /
+ - paragraph [ref=e311]: The Graph for Soroban. Real-time event indexing for the Stellar ecosystem.
+ - link "GitHub" [ref=e312] [cursor=pointer]:
+ - /url: https://github.com/SoroScan/soroscan
+ - img [ref=e313]
+ - text: GitHub
+ - generic [ref=e316]:
+ - heading "PRODUCT" [level=3] [ref=e317]
+ - list [ref=e318]:
+ - listitem [ref=e319]:
+ - link "Home" [ref=e320] [cursor=pointer]:
+ - /url: /
+ - listitem [ref=e321]:
+ - link "Features" [ref=e322] [cursor=pointer]:
+ - /url: /features
+ - listitem [ref=e323]:
+ - link "Dashboard" [ref=e324] [cursor=pointer]:
+ - /url: /dashboard
+ - listitem [ref=e325]:
+ - link "Gallery" [ref=e326] [cursor=pointer]:
+ - /url: /gallery
+ - generic [ref=e327]:
+ - heading "DEVELOPERS" [level=3] [ref=e328]
+ - list [ref=e329]:
+ - listitem [ref=e330]:
+ - link "Documentation" [ref=e331] [cursor=pointer]:
+ - /url: /docs
+ - listitem [ref=e332]:
+ - link "API Docs (Swagger)" [ref=e333] [cursor=pointer]:
+ - /url: /api/docs/
+ - listitem [ref=e334]:
+ - link "API Docs (ReDoc)" [ref=e335] [cursor=pointer]:
+ - /url: /api/redoc/
+ - listitem [ref=e336]:
+ - link "SDK — Python" [ref=e337] [cursor=pointer]:
+ - /url: https://github.com/SoroScan/soroscan
+ - listitem [ref=e338]:
+ - link "SDK — TypeScript" [ref=e339] [cursor=pointer]:
+ - /url: https://github.com/SoroScan/soroscan
+ - generic [ref=e340]:
+ - heading "PROJECT" [level=3] [ref=e341]
+ - list [ref=e342]:
+ - listitem [ref=e343]:
+ - link "GitHub" [ref=e344] [cursor=pointer]:
+ - /url: https://github.com/SoroScan/soroscan
+ - listitem [ref=e345]:
+ - link "Contributing" [ref=e346] [cursor=pointer]:
+ - /url: https://github.com/SoroScan/soroscan/blob/main/CONTRIBUTING.md
+ - listitem [ref=e347]:
+ - link "Stellar Network" [ref=e348] [cursor=pointer]:
+ - /url: https://stellar.org
+ - listitem [ref=e349]:
+ - link "Soroban Docs" [ref=e350] [cursor=pointer]:
+ - /url: https://soroban.stellar.org
+ - generic [ref=e351]:
+ - generic [ref=e352]:
+ - generic [ref=e353]: © 2026 SOROSCAN_INDEXER_SERVICES
+ - link "TERMS_OF_SERVICE" [ref=e354] [cursor=pointer]:
+ - /url: "#"
+ - link "PRIVACY_POLICY" [ref=e355] [cursor=pointer]:
+ - /url: "#"
+ - generic [ref=e356]:
+ - generic [ref=e357]: "STELLAR_MAINNET_UPLINK: ONLINE"
+ - generic [ref=e359]: "LATENCY: 42MS"
+ - generic [ref=e360]: ✓WEBHOOK_CREATED — subscription is now active
+ - button "Open Next.js Dev Tools" [ref=e366] [cursor=pointer]:
+ - img [ref=e367]
+ - alert [ref=e371]
+```
\ No newline at end of file
diff --git a/soroscan-frontend/playwright-report/data/d927c16dc2b2bedc1ec4f4f0be05381fa946ff4e.md b/soroscan-frontend/playwright-report/data/d927c16dc2b2bedc1ec4f4f0be05381fa946ff4e.md
new file mode 100644
index 000000000..d9a990547
--- /dev/null
+++ b/soroscan-frontend/playwright-report/data/d927c16dc2b2bedc1ec4f4f0be05381fa946ff4e.md
@@ -0,0 +1,86 @@
+# Page snapshot
+
+```yaml
+- generic [ref=e1]:
+ - generic [active]:
+ - generic [ref=e4]:
+ - generic [ref=e5]:
+ - generic [ref=e6]:
+ - navigation [ref=e7]:
+ - button "previous" [disabled] [ref=e8]:
+ - img "previous" [ref=e9]
+ - generic [ref=e11]:
+ - generic [ref=e12]: 1/
+ - text: "1"
+ - button "next" [disabled] [ref=e13]:
+ - img "next" [ref=e14]
+ - img
+ - generic [ref=e16]:
+ - generic [ref=e17]:
+ - img [ref=e18]
+ - generic "Latest available version is detected (16.1.6)." [ref=e20]: Next.js 16.1.6
+ - generic [ref=e21]: Turbopack
+ - img
+ - dialog "Runtime TypeError" [ref=e23]:
+ - generic [ref=e26]:
+ - generic [ref=e27]:
+ - generic [ref=e28]:
+ - generic [ref=e30]: Runtime TypeError
+ - generic [ref=e31]:
+ - button "Copy Error Info" [ref=e32] [cursor=pointer]:
+ - img [ref=e33]
+ - button "No related documentation found" [disabled] [ref=e35]:
+ - img [ref=e36]
+ - button "Attach Node.js inspector" [ref=e38] [cursor=pointer]:
+ - img [ref=e39]
+ - generic [ref=e48]: Cannot read properties of undefined (reading 'length')
+ - generic [ref=e49]:
+ - generic [ref=e50]:
+ - paragraph [ref=e52]:
+ - img [ref=e54]
+ - generic [ref=e57]: app/contracts/components/ContractTable.tsx (41:20) @ ContractTable
+ - button "Open in editor" [ref=e58] [cursor=pointer]:
+ - img [ref=e60]
+ - generic [ref=e63]:
+ - generic [ref=e64]: 39 |
+ - generic [ref=e65]: 40 |
+ - generic [ref=e66]: "> 41 | {contracts.length === 0 ? ("
+ - generic [ref=e67]: "| ^"
+ - generic [ref=e68]: 42 |
+ - generic [ref=e69]: "43 | "
+ - generic [ref=e70]: 44 | No contracts registered. Click "Register Contract" to add one.
+ - generic [ref=e71]:
+ - generic [ref=e72]:
+ - paragraph [ref=e73]:
+ - text: Call Stack
+ - generic [ref=e74]: "14"
+ - button "Show 12 ignore-listed frame(s)" [ref=e75] [cursor=pointer]:
+ - text: Show 12 ignore-listed frame(s)
+ - img [ref=e76]
+ - generic [ref=e78]:
+ - generic [ref=e79]:
+ - text: ContractTable
+ - button "Open ContractTable in editor" [ref=e80] [cursor=pointer]:
+ - img [ref=e81]
+ - text: app/contracts/components/ContractTable.tsx (41:20)
+ - generic [ref=e83]:
+ - generic [ref=e84]:
+ - text: ContractsPage
+ - button "Open ContractsPage in editor" [ref=e85] [cursor=pointer]:
+ - img [ref=e86]
+ - text: app/contracts/page.tsx (99:13)
+ - generic [ref=e88]: "1"
+ - generic [ref=e89]: "2"
+ - generic [ref=e94] [cursor=pointer]:
+ - button "Open Next.js Dev Tools" [ref=e95]:
+ - img [ref=e96]
+ - generic [ref=e99]:
+ - button "Open issues overlay" [ref=e100]:
+ - generic [ref=e101]:
+ - generic [ref=e102]: "0"
+ - generic [ref=e103]: "1"
+ - generic [ref=e104]: Issue
+ - button "Collapse issues badge" [ref=e105]:
+ - img [ref=e106]
+ - 'heading "Application error: a client-side exception has occurred while loading localhost (see the browser console for more information)." [level=2] [ref=e110]'
+```
\ No newline at end of file
diff --git a/soroscan-frontend/playwright-report/data/ffd78aca260fa361a8615ec9414ff8ab598c62a7.png b/soroscan-frontend/playwright-report/data/ffd78aca260fa361a8615ec9414ff8ab598c62a7.png
new file mode 100644
index 000000000..dcc500211
Binary files /dev/null and b/soroscan-frontend/playwright-report/data/ffd78aca260fa361a8615ec9414ff8ab598c62a7.png differ
diff --git a/soroscan-frontend/playwright-report/index.html b/soroscan-frontend/playwright-report/index.html
new file mode 100644
index 000000000..27dc82bc8
--- /dev/null
+++ b/soroscan-frontend/playwright-report/index.html
@@ -0,0 +1,85 @@
+
+
+
+
+
+
+
+
+ Playwright Test Report
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/soroscan-frontend/playwright.config.ts b/soroscan-frontend/playwright.config.ts
new file mode 100644
index 000000000..9fe34e289
--- /dev/null
+++ b/soroscan-frontend/playwright.config.ts
@@ -0,0 +1,58 @@
+import { defineConfig, devices } from '@playwright/test';
+
+/**
+ * See https://playwright.dev/docs/test-configuration.
+ */
+export default defineConfig({
+ testDir: './tests',
+ /* Run tests in files in parallel */
+ fullyParallel: true,
+ /* Fail the build on CI if you accidentally left test.only in the source code. */
+ forbidOnly: !!process.env.CI,
+ /* Retry on CI only */
+ retries: process.env.CI ? 2 : 0,
+ /* Opt out of parallel tests on CI. */
+ workers: process.env.CI ? 1 : undefined,
+ /* Reporter to use. See https://playwright.dev/docs/test-reporters */
+ reporter: 'html',
+ /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
+ use: {
+ /* Base URL to use in actions like `await page.goto('/')`. */
+ baseURL: 'http://localhost:3000',
+
+ /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
+ trace: 'on-first-retry',
+
+ /* Capture screenshot on failure */
+ screenshot: 'only-on-failure',
+ },
+
+ /* Configure projects for major browsers */
+ projects: [
+ {
+ name: 'chromium',
+ use: { ...devices['Desktop Chrome'] },
+ },
+
+ {
+ name: 'firefox',
+ use: { ...devices['Desktop Firefox'] },
+ },
+ ],
+
+ /* Run your local dev server before starting the tests */
+ webServer: {
+ command: 'npm run dev',
+ url: 'http://localhost:3000',
+ reuseExistingServer: !process.env.CI,
+ stdout: 'pipe',
+ stderr: 'pipe',
+ },
+
+ /* Visual regression snapshots configuration */
+ expect: {
+ toHaveScreenshot: {
+ maxDiffPixels: 100,
+ },
+ },
+});
diff --git a/soroscan-frontend/pnpm-lock.yaml b/soroscan-frontend/pnpm-lock.yaml
index 6d61e9e4b..87673d802 100644
--- a/soroscan-frontend/pnpm-lock.yaml
+++ b/soroscan-frontend/pnpm-lock.yaml
@@ -31,7 +31,7 @@ importers:
version: 0.575.0(react@19.2.3)
next:
specifier: 16.1.6
- version: 16.1.6(@babel/core@7.29.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
+ version: 16.1.6(@babel/core@7.29.0)(@playwright/test@1.58.2)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
radix-ui:
specifier: ^1.4.3
version: 1.4.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
@@ -63,6 +63,9 @@ importers:
'@graphql-codegen/typescript-operations':
specifier: ^5.0.8
version: 5.0.8(graphql@16.12.0)
+ '@playwright/test':
+ specifier: ^1.58.2
+ version: 1.58.2
'@tailwindcss/postcss':
specifier: ^4
version: 4.2.0
@@ -845,105 +848,89 @@ packages:
resolution: {integrity: sha512-excjX8DfsIcJ10x1Kzr4RcWe1edC9PquDRRPx3YVCvQv+U5p7Yin2s32ftzikXojb1PIFc/9Mt28/y+iRklkrw==}
cpu: [arm64]
os: [linux]
- libc: [glibc]
'@img/sharp-libvips-linux-arm@1.2.4':
resolution: {integrity: sha512-bFI7xcKFELdiNCVov8e44Ia4u2byA+l3XtsAj+Q8tfCwO6BQ8iDojYdvoPMqsKDkuoOo+X6HZA0s0q11ANMQ8A==}
cpu: [arm]
os: [linux]
- libc: [glibc]
'@img/sharp-libvips-linux-ppc64@1.2.4':
resolution: {integrity: sha512-FMuvGijLDYG6lW+b/UvyilUWu5Ayu+3r2d1S8notiGCIyYU/76eig1UfMmkZ7vwgOrzKzlQbFSuQfgm7GYUPpA==}
cpu: [ppc64]
os: [linux]
- libc: [glibc]
'@img/sharp-libvips-linux-riscv64@1.2.4':
resolution: {integrity: sha512-oVDbcR4zUC0ce82teubSm+x6ETixtKZBh/qbREIOcI3cULzDyb18Sr/Wcyx7NRQeQzOiHTNbZFF1UwPS2scyGA==}
cpu: [riscv64]
os: [linux]
- libc: [glibc]
'@img/sharp-libvips-linux-s390x@1.2.4':
resolution: {integrity: sha512-qmp9VrzgPgMoGZyPvrQHqk02uyjA0/QrTO26Tqk6l4ZV0MPWIW6LTkqOIov+J1yEu7MbFQaDpwdwJKhbJvuRxQ==}
cpu: [s390x]
os: [linux]
- libc: [glibc]
'@img/sharp-libvips-linux-x64@1.2.4':
resolution: {integrity: sha512-tJxiiLsmHc9Ax1bz3oaOYBURTXGIRDODBqhveVHonrHJ9/+k89qbLl0bcJns+e4t4rvaNBxaEZsFtSfAdquPrw==}
cpu: [x64]
os: [linux]
- libc: [glibc]
'@img/sharp-libvips-linuxmusl-arm64@1.2.4':
resolution: {integrity: sha512-FVQHuwx1IIuNow9QAbYUzJ+En8KcVm9Lk5+uGUQJHaZmMECZmOlix9HnH7n1TRkXMS0pGxIJokIVB9SuqZGGXw==}
cpu: [arm64]
os: [linux]
- libc: [musl]
'@img/sharp-libvips-linuxmusl-x64@1.2.4':
resolution: {integrity: sha512-+LpyBk7L44ZIXwz/VYfglaX/okxezESc6UxDSoyo2Ks6Jxc4Y7sGjpgU9s4PMgqgjj1gZCylTieNamqA1MF7Dg==}
cpu: [x64]
os: [linux]
- libc: [musl]
'@img/sharp-linux-arm64@0.34.5':
resolution: {integrity: sha512-bKQzaJRY/bkPOXyKx5EVup7qkaojECG6NLYswgktOZjaXecSAeCWiZwwiFf3/Y+O1HrauiE3FVsGxFg8c24rZg==}
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
cpu: [arm64]
os: [linux]
- libc: [glibc]
'@img/sharp-linux-arm@0.34.5':
resolution: {integrity: sha512-9dLqsvwtg1uuXBGZKsxem9595+ujv0sJ6Vi8wcTANSFpwV/GONat5eCkzQo/1O6zRIkh0m/8+5BjrRr7jDUSZw==}
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
cpu: [arm]
os: [linux]
- libc: [glibc]
'@img/sharp-linux-ppc64@0.34.5':
resolution: {integrity: sha512-7zznwNaqW6YtsfrGGDA6BRkISKAAE1Jo0QdpNYXNMHu2+0dTrPflTLNkpc8l7MUP5M16ZJcUvysVWWrMefZquA==}
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
cpu: [ppc64]
os: [linux]
- libc: [glibc]
'@img/sharp-linux-riscv64@0.34.5':
resolution: {integrity: sha512-51gJuLPTKa7piYPaVs8GmByo7/U7/7TZOq+cnXJIHZKavIRHAP77e3N2HEl3dgiqdD/w0yUfiJnII77PuDDFdw==}
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
cpu: [riscv64]
os: [linux]
- libc: [glibc]
'@img/sharp-linux-s390x@0.34.5':
resolution: {integrity: sha512-nQtCk0PdKfho3eC5MrbQoigJ2gd1CgddUMkabUj+rBevs8tZ2cULOx46E7oyX+04WGfABgIwmMC0VqieTiR4jg==}
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
cpu: [s390x]
os: [linux]
- libc: [glibc]
'@img/sharp-linux-x64@0.34.5':
resolution: {integrity: sha512-MEzd8HPKxVxVenwAa+JRPwEC7QFjoPWuS5NZnBt6B3pu7EG2Ge0id1oLHZpPJdn3OQK+BQDiw9zStiHBTJQQQQ==}
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
cpu: [x64]
os: [linux]
- libc: [glibc]
'@img/sharp-linuxmusl-arm64@0.34.5':
resolution: {integrity: sha512-fprJR6GtRsMt6Kyfq44IsChVZeGN97gTD331weR1ex1c1rypDEABN6Tm2xa1wE6lYb5DdEnk03NZPqA7Id21yg==}
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
cpu: [arm64]
os: [linux]
- libc: [musl]
'@img/sharp-linuxmusl-x64@0.34.5':
resolution: {integrity: sha512-Jg8wNT1MUzIvhBFxViqrEhWDGzqymo3sV7z7ZsaWbZNDLXRJZoRGrjulp60YYtV4wfY8VIKcWidjojlLcWrd8Q==}
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
cpu: [x64]
os: [linux]
- libc: [musl]
'@img/sharp-wasm32@0.34.5':
resolution: {integrity: sha512-OdWTEiVkY2PHwqkbBI8frFxQQFekHaSSkUIJkwzclWZe64O1X4UlUjqqqLaPbUpMOQk6FBu/HtlGXNblIs0huw==}
@@ -1265,28 +1252,24 @@ packages:
engines: {node: '>= 10'}
cpu: [arm64]
os: [linux]
- libc: [glibc]
'@next/swc-linux-arm64-musl@16.1.6':
resolution: {integrity: sha512-S4J2v+8tT3NIO9u2q+S0G5KdvNDjXfAv06OhfOzNDaBn5rw84DGXWndOEB7d5/x852A20sW1M56vhC/tRVbccQ==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [linux]
- libc: [musl]
'@next/swc-linux-x64-gnu@16.1.6':
resolution: {integrity: sha512-2eEBDkFlMMNQnkTyPBhQOAyn2qMxyG2eE7GPH2WIDGEpEILcBPI/jdSv4t6xupSP+ot/jkfrCShLAa7+ZUPcJQ==}
engines: {node: '>= 10'}
cpu: [x64]
os: [linux]
- libc: [glibc]
'@next/swc-linux-x64-musl@16.1.6':
resolution: {integrity: sha512-oicJwRlyOoZXVlxmIMaTq7f8pN9QNbdes0q2FXfRsPhfCi8n8JmOZJm5oo1pwDaFbnnD421rVU409M3evFbIqg==}
engines: {node: '>= 10'}
cpu: [x64]
os: [linux]
- libc: [musl]
'@next/swc-win32-arm64-msvc@16.1.6':
resolution: {integrity: sha512-gQmm8izDTPgs+DCWH22kcDmuUp7NyiJgEl18bcr8irXA5N2m2O+JQIr6f3ct42GOs9c0h8QF3L5SzIxcYAAXXw==}
@@ -1345,6 +1328,11 @@ packages:
resolution: {integrity: sha512-QNqXyfVS2wm9hweSYD2O7F0G06uurj9kZ96TRQE5Y9hU7+tgdZwIkbAKc5Ocy1HxEY2kuDQa6cQ1WRs/O5LFKA==}
engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0}
+ '@playwright/test@1.58.2':
+ resolution: {integrity: sha512-akea+6bHYBBfA9uQqSYmlJXn61cTa+jbO87xVLCWbTqbWadRVmhxlXATaOjOgcBaWU4ePo0wB41KMFv3o35IXA==}
+ engines: {node: '>=18'}
+ hasBin: true
+
'@radix-ui/number@1.1.1':
resolution: {integrity: sha512-MkKCwxlXTgz6CFoJx3pCwn07GKp36+aZyu/u2Ln2VrA5DcdyCZkASEDBTd8x5whTQQL5CiYf4prXKLcgQdv29g==}
@@ -2101,28 +2089,24 @@ packages:
engines: {node: '>= 20'}
cpu: [arm64]
os: [linux]
- libc: [glibc]
'@tailwindcss/oxide-linux-arm64-musl@4.2.0':
resolution: {integrity: sha512-XKcSStleEVnbH6W/9DHzZv1YhjE4eSS6zOu2eRtYAIh7aV4o3vIBs+t/B15xlqoxt6ef/0uiqJVB6hkHjWD/0A==}
engines: {node: '>= 20'}
cpu: [arm64]
os: [linux]
- libc: [musl]
'@tailwindcss/oxide-linux-x64-gnu@4.2.0':
resolution: {integrity: sha512-/hlXCBqn9K6fi7eAM0RsobHwJYa5V/xzWspVTzxnX+Ft9v6n+30Pz8+RxCn7sQL/vRHHLS30iQPrHQunu6/vJA==}
engines: {node: '>= 20'}
cpu: [x64]
os: [linux]
- libc: [glibc]
'@tailwindcss/oxide-linux-x64-musl@4.2.0':
resolution: {integrity: sha512-lKUaygq4G7sWkhQbfdRRBkaq4LY39IriqBQ+Gk6l5nKq6Ay2M2ZZb1tlIyRNgZKS8cbErTwuYSor0IIULC0SHw==}
engines: {node: '>= 20'}
cpu: [x64]
os: [linux]
- libc: [musl]
'@tailwindcss/oxide-wasm32-wasi@4.2.0':
resolution: {integrity: sha512-xuDjhAsFdUuFP5W9Ze4k/o4AskUtI8bcAGU4puTYprr89QaYFmhYOPfP+d1pH+k9ets6RoE23BXZM1X1jJqoyw==}
@@ -2374,49 +2358,41 @@ packages:
resolution: {integrity: sha512-34gw7PjDGB9JgePJEmhEqBhWvCiiWCuXsL9hYphDF7crW7UgI05gyBAi6MF58uGcMOiOqSJ2ybEeCvHcq0BCmQ==}
cpu: [arm64]
os: [linux]
- libc: [glibc]
'@unrs/resolver-binding-linux-arm64-musl@1.11.1':
resolution: {integrity: sha512-RyMIx6Uf53hhOtJDIamSbTskA99sPHS96wxVE/bJtePJJtpdKGXO1wY90oRdXuYOGOTuqjT8ACccMc4K6QmT3w==}
cpu: [arm64]
os: [linux]
- libc: [musl]
'@unrs/resolver-binding-linux-ppc64-gnu@1.11.1':
resolution: {integrity: sha512-D8Vae74A4/a+mZH0FbOkFJL9DSK2R6TFPC9M+jCWYia/q2einCubX10pecpDiTmkJVUH+y8K3BZClycD8nCShA==}
cpu: [ppc64]
os: [linux]
- libc: [glibc]
'@unrs/resolver-binding-linux-riscv64-gnu@1.11.1':
resolution: {integrity: sha512-frxL4OrzOWVVsOc96+V3aqTIQl1O2TjgExV4EKgRY09AJ9leZpEg8Ak9phadbuX0BA4k8U5qtvMSQQGGmaJqcQ==}
cpu: [riscv64]
os: [linux]
- libc: [glibc]
'@unrs/resolver-binding-linux-riscv64-musl@1.11.1':
resolution: {integrity: sha512-mJ5vuDaIZ+l/acv01sHoXfpnyrNKOk/3aDoEdLO/Xtn9HuZlDD6jKxHlkN8ZhWyLJsRBxfv9GYM2utQ1SChKew==}
cpu: [riscv64]
os: [linux]
- libc: [musl]
'@unrs/resolver-binding-linux-s390x-gnu@1.11.1':
resolution: {integrity: sha512-kELo8ebBVtb9sA7rMe1Cph4QHreByhaZ2QEADd9NzIQsYNQpt9UkM9iqr2lhGr5afh885d/cB5QeTXSbZHTYPg==}
cpu: [s390x]
os: [linux]
- libc: [glibc]
'@unrs/resolver-binding-linux-x64-gnu@1.11.1':
resolution: {integrity: sha512-C3ZAHugKgovV5YvAMsxhq0gtXuwESUKc5MhEtjBpLoHPLYM+iuwSj3lflFwK3DPm68660rZ7G8BMcwSro7hD5w==}
cpu: [x64]
os: [linux]
- libc: [glibc]
'@unrs/resolver-binding-linux-x64-musl@1.11.1':
resolution: {integrity: sha512-rV0YSoyhK2nZ4vEswT/QwqzqQXw5I6CjoaYMOX0TqBlWhojUf8P94mvI7nuJTeaCkkds3QE4+zS8Ko+GdXuZtA==}
cpu: [x64]
os: [linux]
- libc: [musl]
'@unrs/resolver-binding-wasm32-wasi@1.11.1':
resolution: {integrity: sha512-5u4RkfxJm+Ng7IWgkzi3qrFOvLvQYnPBmjmZQ8+szTK/b31fQCnleNl1GgEt7nIsZRIf5PLhPwT0WM+q45x/UQ==}
@@ -3420,6 +3396,11 @@ packages:
fs.realpath@1.0.0:
resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==}
+ fsevents@2.3.2:
+ resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==}
+ engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
+ os: [darwin]
+
fsevents@2.3.3:
resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==}
engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
@@ -4227,28 +4208,24 @@ packages:
engines: {node: '>= 12.0.0'}
cpu: [arm64]
os: [linux]
- libc: [glibc]
lightningcss-linux-arm64-musl@1.31.1:
resolution: {integrity: sha512-mVZ7Pg2zIbe3XlNbZJdjs86YViQFoJSpc41CbVmKBPiGmC4YrfeOyz65ms2qpAobVd7WQsbW4PdsSJEMymyIMg==}
engines: {node: '>= 12.0.0'}
cpu: [arm64]
os: [linux]
- libc: [musl]
lightningcss-linux-x64-gnu@1.31.1:
resolution: {integrity: sha512-xGlFWRMl+0KvUhgySdIaReQdB4FNudfUTARn7q0hh/V67PVGCs3ADFjw+6++kG1RNd0zdGRlEKa+T13/tQjPMA==}
engines: {node: '>= 12.0.0'}
cpu: [x64]
os: [linux]
- libc: [glibc]
lightningcss-linux-x64-musl@1.31.1:
resolution: {integrity: sha512-eowF8PrKHw9LpoZii5tdZwnBcYDxRw2rRCyvAXLi34iyeYfqCQNA9rmUM0ce62NlPhCvof1+9ivRaTY6pSKDaA==}
engines: {node: '>= 12.0.0'}
cpu: [x64]
os: [linux]
- libc: [musl]
lightningcss-win32-arm64-msvc@1.31.1:
resolution: {integrity: sha512-aJReEbSEQzx1uBlQizAOBSjcmr9dCdL3XuC/6HLXAxmtErsj2ICo5yYggg1qOODQMtnjNQv2UHb9NpOuFtYe4w==}
@@ -4726,6 +4703,16 @@ packages:
resolution: {integrity: sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==}
engines: {node: '>=8'}
+ playwright-core@1.58.2:
+ resolution: {integrity: sha512-yZkEtftgwS8CsfYo7nm0KE8jsvm6i/PTgVtB8DL726wNf6H2IMsDuxCpJj59KDaxCtSnrWan2AeDqM7JBaultg==}
+ engines: {node: '>=18'}
+ hasBin: true
+
+ playwright@1.58.2:
+ resolution: {integrity: sha512-vA30H8Nvkq/cPBnNw4Q8TWz1EJyqgpuinBcHET0YVJVFldr8JDNiU9LaWAE1KqSkRYazuaBhTpB5ZzShOezQ6A==}
+ engines: {node: '>=18'}
+ hasBin: true
+
possible-typed-array-names@1.1.0:
resolution: {integrity: sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==}
engines: {node: '>= 0.4'}
@@ -7292,6 +7279,10 @@ snapshots:
'@pkgr/core@0.2.9': {}
+ '@playwright/test@1.58.2':
+ dependencies:
+ playwright: 1.58.2
+
'@radix-ui/number@1.1.1': {}
'@radix-ui/primitive@1.1.3': {}
@@ -9609,6 +9600,9 @@ snapshots:
fs.realpath@1.0.0: {}
+ fsevents@2.3.2:
+ optional: true
+
fsevents@2.3.3:
optional: true
@@ -10781,7 +10775,7 @@ snapshots:
neo-async@2.6.2: {}
- next@16.1.6(@babel/core@7.29.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3):
+ next@16.1.6(@babel/core@7.29.0)(@playwright/test@1.58.2)(react-dom@19.2.3(react@19.2.3))(react@19.2.3):
dependencies:
'@next/env': 16.1.6
'@swc/helpers': 0.5.15
@@ -10800,6 +10794,7 @@ snapshots:
'@next/swc-linux-x64-musl': 16.1.6
'@next/swc-win32-arm64-msvc': 16.1.6
'@next/swc-win32-x64-msvc': 16.1.6
+ '@playwright/test': 1.58.2
sharp: 0.34.5
transitivePeerDependencies:
- '@babel/core'
@@ -11062,6 +11057,14 @@ snapshots:
dependencies:
find-up: 4.1.0
+ playwright-core@1.58.2: {}
+
+ playwright@1.58.2:
+ dependencies:
+ playwright-core: 1.58.2
+ optionalDependencies:
+ fsevents: 2.3.2
+
possible-typed-array-names@1.1.0: {}
postcss-selector-parser@7.1.1:
diff --git a/soroscan-frontend/src/generated/graphql.ts b/soroscan-frontend/src/generated/graphql.ts
index b1d773474..31343e75e 100644
--- a/soroscan-frontend/src/generated/graphql.ts
+++ b/soroscan-frontend/src/generated/graphql.ts
@@ -1,3 +1,4 @@
+/* eslint-disable */
import type { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core';
export type Maybe = T | null;
export type InputMaybe = T | null | undefined;
diff --git a/soroscan-frontend/test-results/.last-run.json b/soroscan-frontend/test-results/.last-run.json
new file mode 100644
index 000000000..2399833a7
--- /dev/null
+++ b/soroscan-frontend/test-results/.last-run.json
@@ -0,0 +1,13 @@
+{
+ "status": "failed",
+ "failedTests": [
+ "94d2a11b1fc1ed31b81d-794c176b94c9a4889e5e",
+ "42b677eba564a90dbb18-ec2cffff9a12815812d2",
+ "42b677eba564a90dbb18-f8605a16f9fb8cdc2e0c",
+ "9cc65da5bbcc3bc8422c-0325c8a4b2f3190f67cb",
+ "94d2a11b1fc1ed31b81d-a5acd6c5df7840ad3177",
+ "42b677eba564a90dbb18-faaed5d83985a0489676",
+ "42b677eba564a90dbb18-7268b6f2cb9761fe342c",
+ "9cc65da5bbcc3bc8422c-79db730896aa15c56aaf"
+ ]
+}
\ No newline at end of file
diff --git a/soroscan-frontend/test-results/contracts-Contract-Managem-a1c8d-regression---contracts-page-chromium/contracts-actual.png b/soroscan-frontend/test-results/contracts-Contract-Managem-a1c8d-regression---contracts-page-chromium/contracts-actual.png
new file mode 100644
index 000000000..de3753add
Binary files /dev/null and b/soroscan-frontend/test-results/contracts-Contract-Managem-a1c8d-regression---contracts-page-chromium/contracts-actual.png differ
diff --git a/soroscan-frontend/test-results/contracts-Contract-Managem-a1c8d-regression---contracts-page-firefox/contracts-actual.png b/soroscan-frontend/test-results/contracts-Contract-Managem-a1c8d-regression---contracts-page-firefox/contracts-actual.png
new file mode 100644
index 000000000..843a1e1a4
Binary files /dev/null and b/soroscan-frontend/test-results/contracts-Contract-Managem-a1c8d-regression---contracts-page-firefox/contracts-actual.png differ
diff --git a/soroscan-frontend/test-results/contracts-Contract-Management-should-register-a-new-contract-chromium/error-context.md b/soroscan-frontend/test-results/contracts-Contract-Management-should-register-a-new-contract-chromium/error-context.md
new file mode 100644
index 000000000..d9a990547
--- /dev/null
+++ b/soroscan-frontend/test-results/contracts-Contract-Management-should-register-a-new-contract-chromium/error-context.md
@@ -0,0 +1,86 @@
+# Page snapshot
+
+```yaml
+- generic [ref=e1]:
+ - generic [active]:
+ - generic [ref=e4]:
+ - generic [ref=e5]:
+ - generic [ref=e6]:
+ - navigation [ref=e7]:
+ - button "previous" [disabled] [ref=e8]:
+ - img "previous" [ref=e9]
+ - generic [ref=e11]:
+ - generic [ref=e12]: 1/
+ - text: "1"
+ - button "next" [disabled] [ref=e13]:
+ - img "next" [ref=e14]
+ - img
+ - generic [ref=e16]:
+ - generic [ref=e17]:
+ - img [ref=e18]
+ - generic "Latest available version is detected (16.1.6)." [ref=e20]: Next.js 16.1.6
+ - generic [ref=e21]: Turbopack
+ - img
+ - dialog "Runtime TypeError" [ref=e23]:
+ - generic [ref=e26]:
+ - generic [ref=e27]:
+ - generic [ref=e28]:
+ - generic [ref=e30]: Runtime TypeError
+ - generic [ref=e31]:
+ - button "Copy Error Info" [ref=e32] [cursor=pointer]:
+ - img [ref=e33]
+ - button "No related documentation found" [disabled] [ref=e35]:
+ - img [ref=e36]
+ - button "Attach Node.js inspector" [ref=e38] [cursor=pointer]:
+ - img [ref=e39]
+ - generic [ref=e48]: Cannot read properties of undefined (reading 'length')
+ - generic [ref=e49]:
+ - generic [ref=e50]:
+ - paragraph [ref=e52]:
+ - img [ref=e54]
+ - generic [ref=e57]: app/contracts/components/ContractTable.tsx (41:20) @ ContractTable
+ - button "Open in editor" [ref=e58] [cursor=pointer]:
+ - img [ref=e60]
+ - generic [ref=e63]:
+ - generic [ref=e64]: 39 |
+ - generic [ref=e65]: 40 |
+ - generic [ref=e66]: "> 41 | {contracts.length === 0 ? ("
+ - generic [ref=e67]: "| ^"
+ - generic [ref=e68]: 42 |
+ - generic [ref=e69]: "43 | "
+ - generic [ref=e70]: 44 | No contracts registered. Click "Register Contract" to add one.
+ - generic [ref=e71]:
+ - generic [ref=e72]:
+ - paragraph [ref=e73]:
+ - text: Call Stack
+ - generic [ref=e74]: "14"
+ - button "Show 12 ignore-listed frame(s)" [ref=e75] [cursor=pointer]:
+ - text: Show 12 ignore-listed frame(s)
+ - img [ref=e76]
+ - generic [ref=e78]:
+ - generic [ref=e79]:
+ - text: ContractTable
+ - button "Open ContractTable in editor" [ref=e80] [cursor=pointer]:
+ - img [ref=e81]
+ - text: app/contracts/components/ContractTable.tsx (41:20)
+ - generic [ref=e83]:
+ - generic [ref=e84]:
+ - text: ContractsPage
+ - button "Open ContractsPage in editor" [ref=e85] [cursor=pointer]:
+ - img [ref=e86]
+ - text: app/contracts/page.tsx (99:13)
+ - generic [ref=e88]: "1"
+ - generic [ref=e89]: "2"
+ - generic [ref=e94] [cursor=pointer]:
+ - button "Open Next.js Dev Tools" [ref=e95]:
+ - img [ref=e96]
+ - generic [ref=e99]:
+ - button "Open issues overlay" [ref=e100]:
+ - generic [ref=e101]:
+ - generic [ref=e102]: "0"
+ - generic [ref=e103]: "1"
+ - generic [ref=e104]: Issue
+ - button "Collapse issues badge" [ref=e105]:
+ - img [ref=e106]
+ - 'heading "Application error: a client-side exception has occurred while loading localhost (see the browser console for more information)." [level=2] [ref=e110]'
+```
\ No newline at end of file
diff --git a/soroscan-frontend/test-results/contracts-Contract-Management-should-register-a-new-contract-chromium/test-failed-1.png b/soroscan-frontend/test-results/contracts-Contract-Management-should-register-a-new-contract-chromium/test-failed-1.png
new file mode 100644
index 000000000..de3753add
Binary files /dev/null and b/soroscan-frontend/test-results/contracts-Contract-Management-should-register-a-new-contract-chromium/test-failed-1.png differ
diff --git a/soroscan-frontend/test-results/contracts-Contract-Management-should-register-a-new-contract-firefox/error-context.md b/soroscan-frontend/test-results/contracts-Contract-Management-should-register-a-new-contract-firefox/error-context.md
new file mode 100644
index 000000000..4e36224f1
--- /dev/null
+++ b/soroscan-frontend/test-results/contracts-Contract-Management-should-register-a-new-contract-firefox/error-context.md
@@ -0,0 +1,86 @@
+# Page snapshot
+
+```yaml
+- generic [ref=e1]:
+ - generic [active]:
+ - generic [ref=e4]:
+ - generic [ref=e5]:
+ - generic [ref=e6]:
+ - navigation [ref=e7]:
+ - button "previous" [disabled] [ref=e8]:
+ - img "previous" [ref=e9]
+ - generic [ref=e11]:
+ - generic [ref=e12]: 1/
+ - text: "1"
+ - button "next" [disabled] [ref=e13]:
+ - img "next" [ref=e14]
+ - img
+ - generic [ref=e16]:
+ - generic [ref=e17]:
+ - img [ref=e18]
+ - generic "Latest available version is detected (16.1.6)." [ref=e20]: Next.js 16.1.6
+ - generic [ref=e21]: Turbopack
+ - img
+ - dialog "Runtime TypeError" [ref=e23]:
+ - generic [ref=e26]:
+ - generic [ref=e27]:
+ - generic [ref=e28]:
+ - generic [ref=e30]: Runtime TypeError
+ - generic [ref=e31]:
+ - button "Copy Error Info" [ref=e32] [cursor=pointer]:
+ - img [ref=e33]
+ - button "No related documentation found" [disabled] [ref=e35]:
+ - img [ref=e36]
+ - button "Attach Node.js inspector" [ref=e38] [cursor=pointer]:
+ - img [ref=e39]
+ - generic [ref=e48]: can't access property "length", contracts is undefined
+ - generic [ref=e49]:
+ - generic [ref=e50]:
+ - paragraph [ref=e52]:
+ - img [ref=e54]
+ - generic [ref=e57]: app/contracts/components/ContractTable.tsx (40:17) @ ContractTable
+ - button "Open in editor" [ref=e58] [cursor=pointer]:
+ - img [ref=e60]
+ - generic [ref=e63]:
+ - generic [ref=e64]: 38 |
+ - generic [ref=e65]: 39 |
+ - generic [ref=e66]: "> 40 | "
+ - generic [ref=e67]: "| ^"
+ - generic [ref=e68]: "41 | {contracts.length === 0 ? ("
+ - generic [ref=e69]: 42 |
+ - generic [ref=e70]: "43 | "
+ - generic [ref=e71]:
+ - generic [ref=e72]:
+ - paragraph [ref=e73]:
+ - text: Call Stack
+ - generic [ref=e74]: "59"
+ - button "Show 57 ignore-listed frame(s)" [ref=e75] [cursor=pointer]:
+ - text: Show 57 ignore-listed frame(s)
+ - img [ref=e76]
+ - generic [ref=e78]:
+ - generic [ref=e79]:
+ - text: ContractTable
+ - button "Open ContractTable in editor" [ref=e80] [cursor=pointer]:
+ - img [ref=e81]
+ - text: app/contracts/components/ContractTable.tsx (40:17)
+ - generic [ref=e83]:
+ - generic [ref=e84]:
+ - text: ContractsPage
+ - button "Open ContractsPage in editor" [ref=e85] [cursor=pointer]:
+ - img [ref=e86]
+ - text: app/contracts/page.tsx (99:13)
+ - generic [ref=e88]: "1"
+ - generic [ref=e89]: "2"
+ - generic [ref=e94] [cursor=pointer]:
+ - button "Open Next.js Dev Tools" [ref=e95]:
+ - img [ref=e96]
+ - generic [ref=e100]:
+ - button "Open issues overlay" [ref=e101]:
+ - generic [ref=e102]:
+ - generic [ref=e103]: "0"
+ - generic [ref=e104]: "1"
+ - generic [ref=e105]: Issue
+ - button "Collapse issues badge" [ref=e106]:
+ - img [ref=e107]
+ - 'heading "Application error: a client-side exception has occurred while loading localhost (see the browser console for more information)." [level=2] [ref=e111]'
+```
\ No newline at end of file
diff --git a/soroscan-frontend/test-results/contracts-Contract-Management-should-register-a-new-contract-firefox/test-failed-1.png b/soroscan-frontend/test-results/contracts-Contract-Management-should-register-a-new-contract-firefox/test-failed-1.png
new file mode 100644
index 000000000..843a1e1a4
Binary files /dev/null and b/soroscan-frontend/test-results/contracts-Contract-Management-should-register-a-new-contract-firefox/test-failed-1.png differ
diff --git a/soroscan-frontend/test-results/events-Event-Explorer-should-export-events-as-CSV-chromium/error-context.md b/soroscan-frontend/test-results/events-Event-Explorer-should-export-events-as-CSV-chromium/error-context.md
new file mode 100644
index 000000000..de6d4a29c
--- /dev/null
+++ b/soroscan-frontend/test-results/events-Event-Explorer-should-export-events-as-CSV-chromium/error-context.md
@@ -0,0 +1,65 @@
+# Page snapshot
+
+```yaml
+- generic [ref=e1]:
+ - main [ref=e3]:
+ - generic [ref=e4]:
+ - paragraph [ref=e5]: SoroScan
+ - heading "Event Explorer Dashboard" [level=1] [ref=e6]
+ - paragraph [ref=e7]: Browse, filter, and analyze contract events in real-time
+ - region "Event filters" [ref=e8]:
+ - generic [ref=e9]:
+ - heading "Filters" [level=2] [ref=e10]
+ - generic [ref=e11]:
+ - generic [ref=e12]:
+ - generic [ref=e13]: Contract
+ - combobox "Contract" [ref=e14]:
+ - option "All Contracts"
+ - option "Test Token" [selected]
+ - option "Liquidity Pool"
+ - generic [ref=e15]:
+ - generic [ref=e16]: Event Type
+ - combobox "Event Type" [ref=e17]:
+ - option "All Types" [selected]
+ - generic [ref=e18]:
+ - generic [ref=e19]: From
+ - textbox "From" [ref=e20]
+ - generic [ref=e21]:
+ - generic [ref=e22]: To
+ - textbox "To" [ref=e23]
+ - generic [ref=e25]:
+ - generic [ref=e26]: Search
+ - textbox "Search" [ref=e27]:
+ - /placeholder: Search events...
+ - generic [ref=e28]:
+ - button "Apply Filters" [ref=e29] [cursor=pointer]
+ - button "Clear" [ref=e30] [cursor=pointer]
+ - button "Export CSV" [active] [ref=e31] [cursor=pointer]
+ - button "Export JSON" [ref=e32] [cursor=pointer]
+ - region "Events table" [ref=e33]:
+ - generic [ref=e34]:
+ - heading "Contract Events" [level=2] [ref=e35]
+ - paragraph [ref=e36]: Showing 1-0 of 0+
+ - table [ref=e38]:
+ - rowgroup [ref=e39]:
+ - row "Contract Type Ledger Time Transaction Actions" [ref=e40]:
+ - columnheader "Contract" [ref=e41]
+ - columnheader "Type" [ref=e42]
+ - columnheader "Ledger" [ref=e43]
+ - columnheader "Time" [ref=e44]
+ - columnheader "Transaction" [ref=e45]
+ - columnheader "Actions" [ref=e46]
+ - rowgroup [ref=e47]:
+ - row "No events found. Select a contract and adjust filters to view events." [ref=e48]:
+ - cell "No events found. Select a contract and adjust filters to view events." [ref=e49]
+ - generic [ref=e50]:
+ - button "◄◄" [disabled] [ref=e51]
+ - button "◄ Previous" [disabled] [ref=e52]
+ - generic [ref=e53]: Page 1
+ - generic [ref=e54]: Showing 1-0 of 0+
+ - button "Next ►" [disabled] [ref=e55]
+ - button "►►" [disabled] [ref=e56]
+ - button "Open Next.js Dev Tools" [ref=e62] [cursor=pointer]:
+ - img [ref=e63]
+ - alert [ref=e66]
+```
\ No newline at end of file
diff --git a/soroscan-frontend/test-results/events-Event-Explorer-should-export-events-as-CSV-chromium/test-failed-1.png b/soroscan-frontend/test-results/events-Event-Explorer-should-export-events-as-CSV-chromium/test-failed-1.png
new file mode 100644
index 000000000..ff51b9443
Binary files /dev/null and b/soroscan-frontend/test-results/events-Event-Explorer-should-export-events-as-CSV-chromium/test-failed-1.png differ
diff --git a/soroscan-frontend/test-results/events-Event-Explorer-should-export-events-as-CSV-firefox/error-context.md b/soroscan-frontend/test-results/events-Event-Explorer-should-export-events-as-CSV-firefox/error-context.md
new file mode 100644
index 000000000..6daa5f6c2
--- /dev/null
+++ b/soroscan-frontend/test-results/events-Event-Explorer-should-export-events-as-CSV-firefox/error-context.md
@@ -0,0 +1,65 @@
+# Page snapshot
+
+```yaml
+- generic [ref=e1]:
+ - main [ref=e3]:
+ - generic [ref=e4]:
+ - paragraph [ref=e5]: SoroScan
+ - heading "Event Explorer Dashboard" [level=1] [ref=e6]
+ - paragraph [ref=e7]: Browse, filter, and analyze contract events in real-time
+ - region "Event filters" [ref=e8]:
+ - generic [ref=e9]:
+ - heading "Filters" [level=2] [ref=e10]
+ - generic [ref=e11]:
+ - generic [ref=e12]:
+ - generic [ref=e13]: Contract
+ - combobox "Contract" [ref=e14]:
+ - option "All Contracts"
+ - option "Test Token" [selected]
+ - option "Liquidity Pool"
+ - generic [ref=e15]:
+ - generic [ref=e16]: Event Type
+ - combobox "Event Type" [ref=e17]:
+ - option "All Types" [selected]
+ - generic [ref=e18]:
+ - generic [ref=e19]: From
+ - textbox "From" [ref=e20]
+ - generic [ref=e21]:
+ - generic [ref=e22]: To
+ - textbox "To" [ref=e23]
+ - generic [ref=e25]:
+ - generic [ref=e26]: Search
+ - textbox "Search" [ref=e27]:
+ - /placeholder: Search events...
+ - generic [ref=e28]:
+ - button "Apply Filters" [ref=e29] [cursor=pointer]
+ - button "Clear" [ref=e30] [cursor=pointer]
+ - button "Export CSV" [active] [ref=e31] [cursor=pointer]
+ - button "Export JSON" [ref=e32] [cursor=pointer]
+ - region "Events table" [ref=e33]:
+ - generic [ref=e34]:
+ - heading "Contract Events" [level=2] [ref=e35]
+ - paragraph [ref=e36]: Showing 1-0 of 0+
+ - table [ref=e38]:
+ - rowgroup [ref=e39]:
+ - row "Contract Type Ledger Time Transaction Actions" [ref=e40]:
+ - columnheader "Contract" [ref=e41]
+ - columnheader "Type" [ref=e42]
+ - columnheader "Ledger" [ref=e43]
+ - columnheader "Time" [ref=e44]
+ - columnheader "Transaction" [ref=e45]
+ - columnheader "Actions" [ref=e46]
+ - rowgroup [ref=e47]:
+ - row "No events found. Select a contract and adjust filters to view events." [ref=e48]:
+ - cell "No events found. Select a contract and adjust filters to view events." [ref=e49]
+ - generic [ref=e50]:
+ - button "◄◄" [disabled] [ref=e51]
+ - button "◄ Previous" [disabled] [ref=e52]
+ - generic [ref=e53]: Page 1
+ - generic [ref=e54]: Showing 1-0 of 0+
+ - button "Next ►" [disabled] [ref=e55]
+ - button "►►" [disabled] [ref=e56]
+ - button "Open Next.js Dev Tools" [ref=e62] [cursor=pointer]:
+ - img [ref=e63]
+ - alert [ref=e67]
+```
\ No newline at end of file
diff --git a/soroscan-frontend/test-results/events-Event-Explorer-should-export-events-as-CSV-firefox/test-failed-1.png b/soroscan-frontend/test-results/events-Event-Explorer-should-export-events-as-CSV-firefox/test-failed-1.png
new file mode 100644
index 000000000..9b5f6d77d
Binary files /dev/null and b/soroscan-frontend/test-results/events-Event-Explorer-should-export-events-as-CSV-firefox/test-failed-1.png differ
diff --git a/soroscan-frontend/test-results/events-Event-Explorer-should-load-events-and-apply-filters-chromium/error-context.md b/soroscan-frontend/test-results/events-Event-Explorer-should-load-events-and-apply-filters-chromium/error-context.md
new file mode 100644
index 000000000..1819fefd8
--- /dev/null
+++ b/soroscan-frontend/test-results/events-Event-Explorer-should-load-events-and-apply-filters-chromium/error-context.md
@@ -0,0 +1,99 @@
+# Page snapshot
+
+```yaml
+- generic [ref=e1]:
+ - main [ref=e3]:
+ - generic [ref=e4]:
+ - paragraph [ref=e5]: SoroScan
+ - heading "Event Explorer Dashboard" [level=1] [ref=e6]
+ - paragraph [ref=e7]: Browse, filter, and analyze contract events in real-time
+ - region "Event filters" [ref=e8]:
+ - generic [ref=e9]:
+ - heading "Filters" [level=2] [ref=e10]
+ - generic [ref=e11]:
+ - generic [ref=e12]:
+ - generic [ref=e13]: Contract
+ - combobox "Contract" [ref=e14]:
+ - option "All Contracts"
+ - option "Test Token" [selected]
+ - option "Liquidity Pool"
+ - generic [ref=e15]:
+ - generic [ref=e16]: Event Type
+ - combobox "Event Type" [ref=e17]:
+ - option "All Types" [selected]
+ - option "SWAP"
+ - option "MINT"
+ - option "BURN"
+ - option "TRANSFER"
+ - generic [ref=e18]:
+ - generic [ref=e19]: From
+ - textbox "From" [ref=e20]
+ - generic [ref=e21]:
+ - generic [ref=e22]: To
+ - textbox "To" [ref=e23]
+ - generic [ref=e25]:
+ - generic [ref=e26]: Search
+ - textbox "Search" [ref=e27]:
+ - /placeholder: Search events...
+ - generic [ref=e28]:
+ - button "Apply Filters" [active] [ref=e29] [cursor=pointer]
+ - button "Clear" [ref=e30] [cursor=pointer]
+ - button "Export CSV" [ref=e31] [cursor=pointer]
+ - button "Export JSON" [ref=e32] [cursor=pointer]
+ - region "Events table" [ref=e33]:
+ - generic [ref=e34]:
+ - heading "Contract Events" [level=2] [ref=e35]
+ - paragraph [ref=e36]: Showing 1-2 of 2+
+ - table [ref=e38]:
+ - rowgroup [ref=e39]:
+ - row "Contract Type Ledger Time Transaction Actions" [ref=e40]:
+ - columnheader "Contract" [ref=e41]
+ - columnheader "Type" [ref=e42]
+ - columnheader "Ledger" [ref=e43]
+ - columnheader "Time" [ref=e44]
+ - columnheader "Transaction" [ref=e45]
+ - columnheader "Actions" [ref=e46]
+ - rowgroup [ref=e47]:
+ - row "CABC1234...567890 📋 SWAP 1001 02/24/2026, 14:22:49 0x123...abc 📋 View" [ref=e48] [cursor=pointer]:
+ - cell "CABC1234...567890 📋" [ref=e49]:
+ - generic [ref=e50]:
+ - code [ref=e51]: CABC1234...567890
+ - button "📋" [ref=e52]
+ - cell "SWAP" [ref=e53]:
+ - generic [ref=e54]: SWAP
+ - cell "1001" [ref=e55]:
+ - button "1001" [ref=e56]
+ - cell "02/24/2026, 14:22:49" [ref=e57]
+ - cell "0x123...abc 📋" [ref=e58]:
+ - generic [ref=e59]:
+ - code [ref=e60]: 0x123...abc
+ - button "📋" [ref=e61]
+ - cell "View" [ref=e62]:
+ - button "View" [ref=e63]
+ - row "CABC1234...567890 📋 TRANSFER 1002 02/24/2026, 14:22:49 0x456...def 📋 View" [ref=e64] [cursor=pointer]:
+ - cell "CABC1234...567890 📋" [ref=e65]:
+ - generic [ref=e66]:
+ - code [ref=e67]: CABC1234...567890
+ - button "📋" [ref=e68]
+ - cell "TRANSFER" [ref=e69]:
+ - generic [ref=e70]: TRANSFER
+ - cell "1002" [ref=e71]:
+ - button "1002" [ref=e72]
+ - cell "02/24/2026, 14:22:49" [ref=e73]
+ - cell "0x456...def 📋" [ref=e74]:
+ - generic [ref=e75]:
+ - code [ref=e76]: 0x456...def
+ - button "📋" [ref=e77]
+ - cell "View" [ref=e78]:
+ - button "View" [ref=e79]
+ - generic [ref=e80]:
+ - button "◄◄" [disabled] [ref=e81]
+ - button "◄ Previous" [disabled] [ref=e82]
+ - generic [ref=e83]: Page 1
+ - generic [ref=e84]: Showing 1-2 of 2+
+ - button "Next ►" [disabled] [ref=e85]
+ - button "►►" [disabled] [ref=e86]
+ - button "Open Next.js Dev Tools" [ref=e92] [cursor=pointer]:
+ - img [ref=e93]
+ - alert [ref=e96]
+```
\ No newline at end of file
diff --git a/soroscan-frontend/test-results/events-Event-Explorer-should-load-events-and-apply-filters-chromium/test-failed-1.png b/soroscan-frontend/test-results/events-Event-Explorer-should-load-events-and-apply-filters-chromium/test-failed-1.png
new file mode 100644
index 000000000..ab15db16e
Binary files /dev/null and b/soroscan-frontend/test-results/events-Event-Explorer-should-load-events-and-apply-filters-chromium/test-failed-1.png differ
diff --git a/soroscan-frontend/test-results/events-Event-Explorer-should-load-events-and-apply-filters-firefox/error-context.md b/soroscan-frontend/test-results/events-Event-Explorer-should-load-events-and-apply-filters-firefox/error-context.md
new file mode 100644
index 000000000..52c72f47b
--- /dev/null
+++ b/soroscan-frontend/test-results/events-Event-Explorer-should-load-events-and-apply-filters-firefox/error-context.md
@@ -0,0 +1,99 @@
+# Page snapshot
+
+```yaml
+- generic [ref=e1]:
+ - main [ref=e3]:
+ - generic [ref=e4]:
+ - paragraph [ref=e5]: SoroScan
+ - heading "Event Explorer Dashboard" [level=1] [ref=e6]
+ - paragraph [ref=e7]: Browse, filter, and analyze contract events in real-time
+ - region "Event filters" [ref=e8]:
+ - generic [ref=e9]:
+ - heading "Filters" [level=2] [ref=e10]
+ - generic [ref=e11]:
+ - generic [ref=e12]:
+ - generic [ref=e13]: Contract
+ - combobox "Contract" [ref=e14]:
+ - option "All Contracts"
+ - option "Test Token" [selected]
+ - option "Liquidity Pool"
+ - generic [ref=e15]:
+ - generic [ref=e16]: Event Type
+ - combobox "Event Type" [ref=e17]:
+ - option "All Types" [selected]
+ - option "SWAP"
+ - option "MINT"
+ - option "BURN"
+ - option "TRANSFER"
+ - generic [ref=e18]:
+ - generic [ref=e19]: From
+ - textbox "From" [ref=e20]
+ - generic [ref=e21]:
+ - generic [ref=e22]: To
+ - textbox "To" [ref=e23]
+ - generic [ref=e25]:
+ - generic [ref=e26]: Search
+ - textbox "Search" [ref=e27]:
+ - /placeholder: Search events...
+ - generic [ref=e28]:
+ - button "Apply Filters" [active] [ref=e29] [cursor=pointer]
+ - button "Clear" [ref=e30] [cursor=pointer]
+ - button "Export CSV" [ref=e31] [cursor=pointer]
+ - button "Export JSON" [ref=e32] [cursor=pointer]
+ - region "Events table" [ref=e33]:
+ - generic [ref=e34]:
+ - heading "Contract Events" [level=2] [ref=e35]
+ - paragraph [ref=e36]: Showing 1-2 of 2+
+ - table [ref=e38]:
+ - rowgroup [ref=e39]:
+ - row "Contract Type Ledger Time Transaction Actions" [ref=e40]:
+ - columnheader "Contract" [ref=e41]
+ - columnheader "Type" [ref=e42]
+ - columnheader "Ledger" [ref=e43]
+ - columnheader "Time" [ref=e44]
+ - columnheader "Transaction" [ref=e45]
+ - columnheader "Actions" [ref=e46]
+ - rowgroup [ref=e47]:
+ - row "CABC1234...567890 📋 SWAP 1001 02/24/2026, 14:24:02 0x123...abc 📋 View" [ref=e48] [cursor=pointer]:
+ - cell "CABC1234...567890 📋" [ref=e49]:
+ - generic [ref=e50]:
+ - code [ref=e51]: CABC1234...567890
+ - button "📋" [ref=e52]
+ - cell "SWAP" [ref=e53]:
+ - generic [ref=e54]: SWAP
+ - cell "1001" [ref=e55]:
+ - button "1001" [ref=e56]
+ - cell "02/24/2026, 14:24:02" [ref=e57]
+ - cell "0x123...abc 📋" [ref=e58]:
+ - generic [ref=e59]:
+ - code [ref=e60]: 0x123...abc
+ - button "📋" [ref=e61]
+ - cell "View" [ref=e62]:
+ - button "View" [ref=e63]
+ - row "CABC1234...567890 📋 TRANSFER 1002 02/24/2026, 14:24:02 0x456...def 📋 View" [ref=e64] [cursor=pointer]:
+ - cell "CABC1234...567890 📋" [ref=e65]:
+ - generic [ref=e66]:
+ - code [ref=e67]: CABC1234...567890
+ - button "📋" [ref=e68]
+ - cell "TRANSFER" [ref=e69]:
+ - generic [ref=e70]: TRANSFER
+ - cell "1002" [ref=e71]:
+ - button "1002" [ref=e72]
+ - cell "02/24/2026, 14:24:02" [ref=e73]
+ - cell "0x456...def 📋" [ref=e74]:
+ - generic [ref=e75]:
+ - code [ref=e76]: 0x456...def
+ - button "📋" [ref=e77]
+ - cell "View" [ref=e78]:
+ - button "View" [ref=e79]
+ - generic [ref=e80]:
+ - button "◄◄" [disabled] [ref=e81]
+ - button "◄ Previous" [disabled] [ref=e82]
+ - generic [ref=e83]: Page 1
+ - generic [ref=e84]: Showing 1-2 of 2+
+ - button "Next ►" [disabled] [ref=e85]
+ - button "►►" [disabled] [ref=e86]
+ - button "Open Next.js Dev Tools" [ref=e92] [cursor=pointer]:
+ - img [ref=e93]
+ - alert [ref=e97]
+```
\ No newline at end of file
diff --git a/soroscan-frontend/test-results/events-Event-Explorer-should-load-events-and-apply-filters-firefox/test-failed-1.png b/soroscan-frontend/test-results/events-Event-Explorer-should-load-events-and-apply-filters-firefox/test-failed-1.png
new file mode 100644
index 000000000..dcc500211
Binary files /dev/null and b/soroscan-frontend/test-results/events-Event-Explorer-should-load-events-and-apply-filters-firefox/test-failed-1.png differ
diff --git a/soroscan-frontend/test-results/events-Event-Explorer-visual-regression---dashboard-chromium/dashboard-actual.png b/soroscan-frontend/test-results/events-Event-Explorer-visual-regression---dashboard-chromium/dashboard-actual.png
new file mode 100644
index 000000000..fd917b0f2
Binary files /dev/null and b/soroscan-frontend/test-results/events-Event-Explorer-visual-regression---dashboard-chromium/dashboard-actual.png differ
diff --git a/soroscan-frontend/test-results/events-Event-Explorer-visual-regression---dashboard-firefox/dashboard-actual.png b/soroscan-frontend/test-results/events-Event-Explorer-visual-regression---dashboard-firefox/dashboard-actual.png
new file mode 100644
index 000000000..e4d9438ea
Binary files /dev/null and b/soroscan-frontend/test-results/events-Event-Explorer-visual-regression---dashboard-firefox/dashboard-actual.png differ
diff --git a/soroscan-frontend/test-results/webhooks-Webhook-Manager-should-create-and-test-a-webhook-chromium/error-context.md b/soroscan-frontend/test-results/webhooks-Webhook-Manager-should-create-and-test-a-webhook-chromium/error-context.md
new file mode 100644
index 000000000..0cde90259
--- /dev/null
+++ b/soroscan-frontend/test-results/webhooks-Webhook-Manager-should-create-and-test-a-webhook-chromium/error-context.md
@@ -0,0 +1,328 @@
+# Page snapshot
+
+```yaml
+- generic [active] [ref=e1]:
+ - generic [ref=e2]:
+ - navigation [ref=e3]:
+ - generic [ref=e4]:
+ - link "[SOROSCAN]" [ref=e5] [cursor=pointer]:
+ - /url: /
+ - generic [ref=e6]:
+ - link "DOCS" [ref=e7] [cursor=pointer]:
+ - /url: /docs
+ - link "FEATURES" [ref=e8] [cursor=pointer]:
+ - /url: /features
+ - link "API_DOCS" [ref=e9] [cursor=pointer]:
+ - /url: /api/docs/
+ - link "GITHUB" [ref=e10] [cursor=pointer]:
+ - /url: https://github.com/SoroScan/soroscan
+ - link "> GET_API_KEY" [ref=e12] [cursor=pointer]:
+ - /url: /api/docs/
+ - button "> GET_API_KEY" [ref=e13]:
+ - generic [ref=e14]:
+ - generic [ref=e15]: ">"
+ - text: GET_API_KEY
+ - main [ref=e16]:
+ - generic [ref=e17]:
+ - generic [ref=e18]:
+ - generic [ref=e19]: "[WEBHOOK_MANAGER]"
+ - heading "SUBSCRIPTIONS" [level=1] [ref=e20]
+ - paragraph [ref=e21]: 6 subscriptions configured
+ - button "> NEW_WEBHOOK" [ref=e22]:
+ - generic [ref=e23]:
+ - generic [ref=e24]: ">"
+ - img [ref=e25]
+ - text: NEW_WEBHOOK
+ - generic [ref=e26]:
+ - generic [ref=e27]:
+ - generic [ref=e28]: "6"
+ - generic [ref=e29]: TOTAL
+ - generic [ref=e30]:
+ - generic [ref=e31]:
+ - img [ref=e32]
+ - text: "4"
+ - generic [ref=e34]: ACTIVE
+ - generic [ref=e35]:
+ - generic [ref=e36]:
+ - img [ref=e37]
+ - text: "1"
+ - generic [ref=e39]: FAILED
+ - generic [ref=e40]:
+ - generic [ref=e41]: 80.7%
+ - generic [ref=e42]: AVG_SUCCESS
+ - generic [ref=e43]: "LAST_EVENT: 23/02/2026, 23:34:01"
+ - generic [ref=e45]:
+ - heading "[WEBHOOK_LIST]" [level=2] [ref=e47]
+ - table [ref=e51]:
+ - rowgroup [ref=e52]:
+ - row "STATUS ENDPOINT_URL EVENT_TYPES SUCCESS LAST_DELIVERY ACTIONS" [ref=e53]:
+ - columnheader "STATUS" [ref=e54] [cursor=pointer]:
+ - generic [ref=e55]:
+ - text: STATUS
+ - img [ref=e56]
+ - columnheader "ENDPOINT_URL" [ref=e58] [cursor=pointer]:
+ - generic [ref=e59]:
+ - text: ENDPOINT_URL
+ - img [ref=e60]
+ - columnheader "EVENT_TYPES" [ref=e62]
+ - columnheader "SUCCESS" [ref=e63] [cursor=pointer]:
+ - generic [ref=e64]:
+ - text: SUCCESS
+ - img [ref=e65]
+ - columnheader "LAST_DELIVERY" [ref=e67] [cursor=pointer]:
+ - generic [ref=e68]:
+ - text: LAST_DELIVERY
+ - img [ref=e69]
+ - columnheader "ACTIONS" [ref=e71]
+ - rowgroup [ref=e72]:
+ - 'row "ACTIVE https://api.myapp.io/hooks/soroban CONTRACT: CABC...9X4Z SWAP_COMPLETE LIQUIDITY_ADD 98.7% 23/02/2026, 23:34 HTTP 200 > DETAIL" [ref=e73]':
+ - cell "ACTIVE" [ref=e74]:
+ - generic [ref=e75]: ACTIVE
+ - 'cell "https://api.myapp.io/hooks/soroban CONTRACT: CABC...9X4Z" [ref=e77]':
+ - generic [ref=e78]:
+ - link "https://api.myapp.io/hooks/soroban" [ref=e79] [cursor=pointer]:
+ - /url: /webhooks/wh_001
+ - generic [ref=e80]: "CONTRACT: CABC...9X4Z"
+ - cell "SWAP_COMPLETE LIQUIDITY_ADD" [ref=e81]:
+ - generic [ref=e82]:
+ - generic [ref=e83]: SWAP_COMPLETE
+ - generic [ref=e84]: LIQUIDITY_ADD
+ - cell "98.7%" [ref=e85]:
+ - generic [ref=e89]: 98.7%
+ - cell "23/02/2026, 23:34 HTTP 200" [ref=e90]:
+ - text: 23/02/2026, 23:34
+ - generic [ref=e91]: HTTP 200
+ - cell "> DETAIL" [ref=e92]:
+ - generic [ref=e93]:
+ - link "> DETAIL" [ref=e94] [cursor=pointer]:
+ - /url: /webhooks/wh_001
+ - button "> DETAIL" [ref=e95]:
+ - generic [ref=e96]:
+ - generic [ref=e97]: ">"
+ - text: DETAIL
+ - button "Test webhook" [ref=e98]:
+ - img [ref=e99]
+ - button "Delete webhook" [ref=e101]:
+ - img [ref=e102]
+ - row "ACTIVE https://realtime.indexer.finance/soroscan-events ORACLE_UPDATE STAKING_LOCK SWAP_COMPLETE 99.1% 23/02/2026, 23:33 HTTP 200 > DETAIL" [ref=e105]:
+ - cell "ACTIVE" [ref=e106]:
+ - generic [ref=e107]: ACTIVE
+ - cell "https://realtime.indexer.finance/soroscan-events" [ref=e109]:
+ - link "https://realtime.indexer.finance/soroscan-events" [ref=e111] [cursor=pointer]:
+ - /url: /webhooks/wh_005
+ - cell "ORACLE_UPDATE STAKING_LOCK SWAP_COMPLETE" [ref=e112]:
+ - generic [ref=e113]:
+ - generic [ref=e114]: ORACLE_UPDATE
+ - generic [ref=e115]: STAKING_LOCK
+ - generic [ref=e116]: SWAP_COMPLETE
+ - cell "99.1%" [ref=e117]:
+ - generic [ref=e121]: 99.1%
+ - cell "23/02/2026, 23:33 HTTP 200" [ref=e122]:
+ - text: 23/02/2026, 23:33
+ - generic [ref=e123]: HTTP 200
+ - cell "> DETAIL" [ref=e124]:
+ - generic [ref=e125]:
+ - link "> DETAIL" [ref=e126] [cursor=pointer]:
+ - /url: /webhooks/wh_005
+ - button "> DETAIL" [ref=e127]:
+ - generic [ref=e128]:
+ - generic [ref=e129]: ">"
+ - text: DETAIL
+ - button "Test webhook" [ref=e130]:
+ - img [ref=e131]
+ - button "Delete webhook" [ref=e133]:
+ - img [ref=e134]
+ - row "ACTIVE https://webhook.site/abc123def456 ALL_EVENTS 100.0% 23/02/2026, 23:31 HTTP 200 > DETAIL" [ref=e137]:
+ - cell "ACTIVE" [ref=e138]:
+ - generic [ref=e139]: ACTIVE
+ - cell "https://webhook.site/abc123def456" [ref=e141]:
+ - link "https://webhook.site/abc123def456" [ref=e143] [cursor=pointer]:
+ - /url: /webhooks/wh_002
+ - cell "ALL_EVENTS" [ref=e144]:
+ - generic [ref=e146]: ALL_EVENTS
+ - cell "100.0%" [ref=e147]:
+ - generic [ref=e151]: 100.0%
+ - cell "23/02/2026, 23:31 HTTP 200" [ref=e152]:
+ - text: 23/02/2026, 23:31
+ - generic [ref=e153]: HTTP 200
+ - cell "> DETAIL" [ref=e154]:
+ - generic [ref=e155]:
+ - link "> DETAIL" [ref=e156] [cursor=pointer]:
+ - /url: /webhooks/wh_002
+ - button "> DETAIL" [ref=e157]:
+ - generic [ref=e158]:
+ - generic [ref=e159]: ">"
+ - text: DETAIL
+ - button "Test webhook" [ref=e160]:
+ - img [ref=e161]
+ - button "Delete webhook" [ref=e163]:
+ - img [ref=e164]
+ - row "FAILED https://hooks.internal.corp/blockchain-events GOV_PROPOSAL 12.1% 23/02/2026, 21:55 HTTP 404 > DETAIL" [ref=e167]:
+ - cell "FAILED" [ref=e168]:
+ - generic [ref=e169]: FAILED
+ - cell "https://hooks.internal.corp/blockchain-events" [ref=e171]:
+ - link "https://hooks.internal.corp/blockchain-events" [ref=e173] [cursor=pointer]:
+ - /url: /webhooks/wh_004
+ - cell "GOV_PROPOSAL" [ref=e174]:
+ - generic [ref=e176]: GOV_PROPOSAL
+ - cell "12.1%" [ref=e177]:
+ - generic [ref=e181]: 12.1%
+ - cell "23/02/2026, 21:55 HTTP 404" [ref=e182]:
+ - text: 23/02/2026, 21:55
+ - generic [ref=e183]: HTTP 404
+ - cell "> DETAIL" [ref=e184]:
+ - generic [ref=e185]:
+ - link "> DETAIL" [ref=e186] [cursor=pointer]:
+ - /url: /webhooks/wh_004
+ - button "> DETAIL" [ref=e187]:
+ - generic [ref=e188]:
+ - generic [ref=e189]: ">"
+ - text: DETAIL
+ - button "Test webhook" [ref=e190]:
+ - img [ref=e191]
+ - button "Delete webhook" [ref=e193]:
+ - img [ref=e194]
+ - 'row "SUSPENDED https://events.defiprotocol.org/soroscan CONTRACT: CGHI...F7K1 VAULT_DEPOSIT YIELD_CLAIMED 74.2% 21/02/2026, 09:10 HTTP 503 > DETAIL" [ref=e197]':
+ - cell "SUSPENDED" [ref=e198]:
+ - generic [ref=e199]: SUSPENDED
+ - 'cell "https://events.defiprotocol.org/soroscan CONTRACT: CGHI...F7K1" [ref=e201]':
+ - generic [ref=e202]:
+ - link "https://events.defiprotocol.org/soroscan" [ref=e203] [cursor=pointer]:
+ - /url: /webhooks/wh_003
+ - generic [ref=e204]: "CONTRACT: CGHI...F7K1"
+ - cell "VAULT_DEPOSIT YIELD_CLAIMED" [ref=e205]:
+ - generic [ref=e206]:
+ - generic [ref=e207]: VAULT_DEPOSIT
+ - generic [ref=e208]: YIELD_CLAIMED
+ - cell "74.2%" [ref=e209]:
+ - generic [ref=e213]: 74.2%
+ - cell "21/02/2026, 09:10 HTTP 503" [ref=e214]:
+ - text: 21/02/2026, 09:10
+ - generic [ref=e215]: HTTP 503
+ - cell "> DETAIL" [ref=e216]:
+ - generic [ref=e217]:
+ - link "> DETAIL" [ref=e218] [cursor=pointer]:
+ - /url: /webhooks/wh_003
+ - button "> DETAIL" [ref=e219]:
+ - generic [ref=e220]:
+ - generic [ref=e221]: ">"
+ - text: DETAIL
+ - button "Test webhook" [ref=e222]:
+ - img [ref=e223]
+ - button "Delete webhook" [ref=e225]:
+ - img [ref=e226]
+ - row "ACTIVE https://example.com/webhook ALL_EVENTS 100.0% — > DETAIL" [ref=e229]:
+ - cell "ACTIVE" [ref=e230]:
+ - generic [ref=e231]: ACTIVE
+ - cell "https://example.com/webhook" [ref=e233]:
+ - link "https://example.com/webhook" [ref=e235] [cursor=pointer]:
+ - /url: /webhooks/wh_ejsu7
+ - cell "ALL_EVENTS" [ref=e236]:
+ - generic [ref=e238]: ALL_EVENTS
+ - cell "100.0%" [ref=e239]:
+ - generic [ref=e243]: 100.0%
+ - cell "—" [ref=e244]
+ - cell "> DETAIL" [ref=e245]:
+ - generic [ref=e246]:
+ - link "> DETAIL" [ref=e247] [cursor=pointer]:
+ - /url: /webhooks/wh_ejsu7
+ - button "> DETAIL" [ref=e248]:
+ - generic [ref=e249]:
+ - generic [ref=e250]: ">"
+ - text: DETAIL
+ - button "Test webhook" [disabled] [ref=e251]:
+ - img [ref=e252]
+ - button "Delete webhook" [ref=e254]:
+ - img [ref=e255]
+ - generic [ref=e258]:
+ - generic [ref=e259]:
+ - generic [ref=e260]: SYSTEM_OVERRIDE_ACTIVE
+ - generic [ref=e261]: "AUTH_MODE: DEV_OPEN"
+ - heading "READY_TO_UPLINK?" [level=2] [ref=e262]
+ - paragraph [ref=e263]: Join the decentralised indexing network and fuel your Soroban dApps with high-fidelity event data — free during open beta.
+ - generic [ref=e264]:
+ - link "> GET_API_KEY" [ref=e265] [cursor=pointer]:
+ - /url: /api/docs/
+ - button "> GET_API_KEY" [ref=e266]:
+ - generic [ref=e267]:
+ - generic [ref=e268]: ">"
+ - text: GET_API_KEY
+ - link "> READ_DOCS" [ref=e269] [cursor=pointer]:
+ - /url: /docs
+ - button "> READ_DOCS" [ref=e270]:
+ - generic [ref=e271]:
+ - generic [ref=e272]: ">"
+ - text: READ_DOCS
+ - contentinfo [ref=e273]:
+ - generic [ref=e274]:
+ - generic [ref=e275]:
+ - link "[SOROSCAN]" [ref=e276] [cursor=pointer]:
+ - /url: /
+ - paragraph [ref=e277]: The Graph for Soroban. Real-time event indexing for the Stellar ecosystem.
+ - link "GitHub" [ref=e278] [cursor=pointer]:
+ - /url: https://github.com/SoroScan/soroscan
+ - img [ref=e279]
+ - text: GitHub
+ - generic [ref=e282]:
+ - heading "PRODUCT" [level=3] [ref=e283]
+ - list [ref=e284]:
+ - listitem [ref=e285]:
+ - link "Home" [ref=e286] [cursor=pointer]:
+ - /url: /
+ - listitem [ref=e287]:
+ - link "Features" [ref=e288] [cursor=pointer]:
+ - /url: /features
+ - listitem [ref=e289]:
+ - link "Dashboard" [ref=e290] [cursor=pointer]:
+ - /url: /dashboard
+ - listitem [ref=e291]:
+ - link "Gallery" [ref=e292] [cursor=pointer]:
+ - /url: /gallery
+ - generic [ref=e293]:
+ - heading "DEVELOPERS" [level=3] [ref=e294]
+ - list [ref=e295]:
+ - listitem [ref=e296]:
+ - link "Documentation" [ref=e297] [cursor=pointer]:
+ - /url: /docs
+ - listitem [ref=e298]:
+ - link "API Docs (Swagger)" [ref=e299] [cursor=pointer]:
+ - /url: /api/docs/
+ - listitem [ref=e300]:
+ - link "API Docs (ReDoc)" [ref=e301] [cursor=pointer]:
+ - /url: /api/redoc/
+ - listitem [ref=e302]:
+ - link "SDK — Python" [ref=e303] [cursor=pointer]:
+ - /url: https://github.com/SoroScan/soroscan
+ - listitem [ref=e304]:
+ - link "SDK — TypeScript" [ref=e305] [cursor=pointer]:
+ - /url: https://github.com/SoroScan/soroscan
+ - generic [ref=e306]:
+ - heading "PROJECT" [level=3] [ref=e307]
+ - list [ref=e308]:
+ - listitem [ref=e309]:
+ - link "GitHub" [ref=e310] [cursor=pointer]:
+ - /url: https://github.com/SoroScan/soroscan
+ - listitem [ref=e311]:
+ - link "Contributing" [ref=e312] [cursor=pointer]:
+ - /url: https://github.com/SoroScan/soroscan/blob/main/CONTRIBUTING.md
+ - listitem [ref=e313]:
+ - link "Stellar Network" [ref=e314] [cursor=pointer]:
+ - /url: https://stellar.org
+ - listitem [ref=e315]:
+ - link "Soroban Docs" [ref=e316] [cursor=pointer]:
+ - /url: https://soroban.stellar.org
+ - generic [ref=e317]:
+ - generic [ref=e318]:
+ - generic [ref=e319]: © 2026 SOROSCAN_INDEXER_SERVICES
+ - link "TERMS_OF_SERVICE" [ref=e320] [cursor=pointer]:
+ - /url: "#"
+ - link "PRIVACY_POLICY" [ref=e321] [cursor=pointer]:
+ - /url: "#"
+ - generic [ref=e322]:
+ - generic [ref=e323]: "STELLAR_MAINNET_UPLINK: ONLINE"
+ - generic [ref=e325]: "LATENCY: 42MS"
+ - generic [ref=e326]: ✓WEBHOOK_CREATED — subscription is now active
+ - button "Open Next.js Dev Tools" [ref=e332] [cursor=pointer]:
+ - img [ref=e333]
+ - alert [ref=e336]
+```
\ No newline at end of file
diff --git a/soroscan-frontend/test-results/webhooks-Webhook-Manager-should-create-and-test-a-webhook-chromium/test-failed-1.png b/soroscan-frontend/test-results/webhooks-Webhook-Manager-should-create-and-test-a-webhook-chromium/test-failed-1.png
new file mode 100644
index 000000000..d3ea64e03
Binary files /dev/null and b/soroscan-frontend/test-results/webhooks-Webhook-Manager-should-create-and-test-a-webhook-chromium/test-failed-1.png differ
diff --git a/soroscan-frontend/test-results/webhooks-Webhook-Manager-should-create-and-test-a-webhook-firefox/error-context.md b/soroscan-frontend/test-results/webhooks-Webhook-Manager-should-create-and-test-a-webhook-firefox/error-context.md
new file mode 100644
index 000000000..20565060c
--- /dev/null
+++ b/soroscan-frontend/test-results/webhooks-Webhook-Manager-should-create-and-test-a-webhook-firefox/error-context.md
@@ -0,0 +1,328 @@
+# Page snapshot
+
+```yaml
+- generic [active] [ref=e1]:
+ - generic [ref=e2]:
+ - navigation [ref=e3]:
+ - generic [ref=e4]:
+ - link "[SOROSCAN]" [ref=e5] [cursor=pointer]:
+ - /url: /
+ - generic [ref=e6]:
+ - link "DOCS" [ref=e7] [cursor=pointer]:
+ - /url: /docs
+ - link "FEATURES" [ref=e8] [cursor=pointer]:
+ - /url: /features
+ - link "API_DOCS" [ref=e9] [cursor=pointer]:
+ - /url: /api/docs/
+ - link "GITHUB" [ref=e10] [cursor=pointer]:
+ - /url: https://github.com/SoroScan/soroscan
+ - link "> GET_API_KEY" [ref=e12] [cursor=pointer]:
+ - /url: /api/docs/
+ - button "> GET_API_KEY" [ref=e13]:
+ - generic [ref=e14]:
+ - generic [ref=e15]: ">"
+ - text: GET_API_KEY
+ - main [ref=e16]:
+ - generic [ref=e17]:
+ - generic [ref=e18]:
+ - generic [ref=e19]: "[WEBHOOK_MANAGER]"
+ - heading "SUBSCRIPTIONS" [level=1] [ref=e20]
+ - paragraph [ref=e21]: 6 subscriptions configured
+ - button "> NEW_WEBHOOK" [ref=e22]:
+ - generic [ref=e23]:
+ - generic [ref=e24]: ">"
+ - img [ref=e25]
+ - text: NEW_WEBHOOK
+ - generic [ref=e28]:
+ - generic [ref=e29]:
+ - generic [ref=e30]: "6"
+ - generic [ref=e31]: TOTAL
+ - generic [ref=e32]:
+ - generic [ref=e33]:
+ - img [ref=e34]
+ - text: "4"
+ - generic [ref=e36]: ACTIVE
+ - generic [ref=e37]:
+ - generic [ref=e38]:
+ - img [ref=e39]
+ - text: "1"
+ - generic [ref=e43]: FAILED
+ - generic [ref=e44]:
+ - generic [ref=e45]: 80.7%
+ - generic [ref=e46]: AVG_SUCCESS
+ - generic [ref=e47]: "LAST_EVENT: 23/02/2026, 23:34:01"
+ - generic [ref=e49]:
+ - heading "[WEBHOOK_LIST]" [level=2] [ref=e51]
+ - table [ref=e55]:
+ - rowgroup [ref=e56]:
+ - row "STATUS ENDPOINT_URL EVENT_TYPES SUCCESS LAST_DELIVERY ACTIONS" [ref=e57]:
+ - columnheader "STATUS" [ref=e58] [cursor=pointer]:
+ - generic [ref=e59]:
+ - text: STATUS
+ - img [ref=e60]
+ - columnheader "ENDPOINT_URL" [ref=e62] [cursor=pointer]:
+ - generic [ref=e63]:
+ - text: ENDPOINT_URL
+ - img [ref=e64]
+ - columnheader "EVENT_TYPES" [ref=e66]
+ - columnheader "SUCCESS" [ref=e67] [cursor=pointer]:
+ - generic [ref=e68]:
+ - text: SUCCESS
+ - img [ref=e69]
+ - columnheader "LAST_DELIVERY" [ref=e71] [cursor=pointer]:
+ - generic [ref=e72]:
+ - text: LAST_DELIVERY
+ - img [ref=e73]
+ - columnheader "ACTIONS" [ref=e75]
+ - rowgroup [ref=e76]:
+ - 'row "ACTIVE https://api.myapp.io/hooks/soroban CONTRACT: CABC...9X4Z SWAP_COMPLETE LIQUIDITY_ADD 98.7% 23/02/2026, 23:34 HTTP 200 > DETAIL" [ref=e77]':
+ - cell "ACTIVE" [ref=e78]:
+ - generic [ref=e79]: ACTIVE
+ - 'cell "https://api.myapp.io/hooks/soroban CONTRACT: CABC...9X4Z" [ref=e81]':
+ - generic [ref=e82]:
+ - link "https://api.myapp.io/hooks/soroban" [ref=e83] [cursor=pointer]:
+ - /url: /webhooks/wh_001
+ - generic [ref=e84]: "CONTRACT: CABC...9X4Z"
+ - cell "SWAP_COMPLETE LIQUIDITY_ADD" [ref=e85]:
+ - generic [ref=e86]:
+ - generic [ref=e87]: SWAP_COMPLETE
+ - generic [ref=e88]: LIQUIDITY_ADD
+ - cell "98.7%" [ref=e89]:
+ - generic [ref=e93]: 98.7%
+ - cell "23/02/2026, 23:34 HTTP 200" [ref=e94]:
+ - text: 23/02/2026, 23:34
+ - generic [ref=e95]: HTTP 200
+ - cell "> DETAIL" [ref=e96]:
+ - generic [ref=e97]:
+ - link "> DETAIL" [ref=e98] [cursor=pointer]:
+ - /url: /webhooks/wh_001
+ - button "> DETAIL" [ref=e99]:
+ - generic [ref=e100]:
+ - generic [ref=e101]: ">"
+ - text: DETAIL
+ - button "Test webhook" [ref=e102]:
+ - img [ref=e103]
+ - button "Delete webhook" [ref=e107]:
+ - img [ref=e108]
+ - row "ACTIVE https://realtime.indexer.finance/soroscan-events ORACLE_UPDATE STAKING_LOCK SWAP_COMPLETE 99.1% 23/02/2026, 23:33 HTTP 200 > DETAIL" [ref=e114]:
+ - cell "ACTIVE" [ref=e115]:
+ - generic [ref=e116]: ACTIVE
+ - cell "https://realtime.indexer.finance/soroscan-events" [ref=e118]:
+ - link "https://realtime.indexer.finance/soroscan-events" [ref=e120] [cursor=pointer]:
+ - /url: /webhooks/wh_005
+ - cell "ORACLE_UPDATE STAKING_LOCK SWAP_COMPLETE" [ref=e121]:
+ - generic [ref=e122]:
+ - generic [ref=e123]: ORACLE_UPDATE
+ - generic [ref=e124]: STAKING_LOCK
+ - generic [ref=e125]: SWAP_COMPLETE
+ - cell "99.1%" [ref=e126]:
+ - generic [ref=e130]: 99.1%
+ - cell "23/02/2026, 23:33 HTTP 200" [ref=e131]:
+ - text: 23/02/2026, 23:33
+ - generic [ref=e132]: HTTP 200
+ - cell "> DETAIL" [ref=e133]:
+ - generic [ref=e134]:
+ - link "> DETAIL" [ref=e135] [cursor=pointer]:
+ - /url: /webhooks/wh_005
+ - button "> DETAIL" [ref=e136]:
+ - generic [ref=e137]:
+ - generic [ref=e138]: ">"
+ - text: DETAIL
+ - button "Test webhook" [ref=e139]:
+ - img [ref=e140]
+ - button "Delete webhook" [ref=e144]:
+ - img [ref=e145]
+ - row "ACTIVE https://webhook.site/abc123def456 ALL_EVENTS 100.0% 23/02/2026, 23:31 HTTP 200 > DETAIL" [ref=e151]:
+ - cell "ACTIVE" [ref=e152]:
+ - generic [ref=e153]: ACTIVE
+ - cell "https://webhook.site/abc123def456" [ref=e155]:
+ - link "https://webhook.site/abc123def456" [ref=e157] [cursor=pointer]:
+ - /url: /webhooks/wh_002
+ - cell "ALL_EVENTS" [ref=e158]:
+ - generic [ref=e160]: ALL_EVENTS
+ - cell "100.0%" [ref=e161]:
+ - generic [ref=e165]: 100.0%
+ - cell "23/02/2026, 23:31 HTTP 200" [ref=e166]:
+ - text: 23/02/2026, 23:31
+ - generic [ref=e167]: HTTP 200
+ - cell "> DETAIL" [ref=e168]:
+ - generic [ref=e169]:
+ - link "> DETAIL" [ref=e170] [cursor=pointer]:
+ - /url: /webhooks/wh_002
+ - button "> DETAIL" [ref=e171]:
+ - generic [ref=e172]:
+ - generic [ref=e173]: ">"
+ - text: DETAIL
+ - button "Test webhook" [ref=e174]:
+ - img [ref=e175]
+ - button "Delete webhook" [ref=e179]:
+ - img [ref=e180]
+ - row "FAILED https://hooks.internal.corp/blockchain-events GOV_PROPOSAL 12.1% 23/02/2026, 21:55 HTTP 404 > DETAIL" [ref=e186]:
+ - cell "FAILED" [ref=e187]:
+ - generic [ref=e188]: FAILED
+ - cell "https://hooks.internal.corp/blockchain-events" [ref=e190]:
+ - link "https://hooks.internal.corp/blockchain-events" [ref=e192] [cursor=pointer]:
+ - /url: /webhooks/wh_004
+ - cell "GOV_PROPOSAL" [ref=e193]:
+ - generic [ref=e195]: GOV_PROPOSAL
+ - cell "12.1%" [ref=e196]:
+ - generic [ref=e200]: 12.1%
+ - cell "23/02/2026, 21:55 HTTP 404" [ref=e201]:
+ - text: 23/02/2026, 21:55
+ - generic [ref=e202]: HTTP 404
+ - cell "> DETAIL" [ref=e203]:
+ - generic [ref=e204]:
+ - link "> DETAIL" [ref=e205] [cursor=pointer]:
+ - /url: /webhooks/wh_004
+ - button "> DETAIL" [ref=e206]:
+ - generic [ref=e207]:
+ - generic [ref=e208]: ">"
+ - text: DETAIL
+ - button "Test webhook" [ref=e209]:
+ - img [ref=e210]
+ - button "Delete webhook" [ref=e214]:
+ - img [ref=e215]
+ - 'row "SUSPENDED https://events.defiprotocol.org/soroscan CONTRACT: CGHI...F7K1 VAULT_DEPOSIT YIELD_CLAIMED 74.2% 21/02/2026, 09:10 HTTP 503 > DETAIL" [ref=e221]':
+ - cell "SUSPENDED" [ref=e222]:
+ - generic [ref=e223]: SUSPENDED
+ - 'cell "https://events.defiprotocol.org/soroscan CONTRACT: CGHI...F7K1" [ref=e225]':
+ - generic [ref=e226]:
+ - link "https://events.defiprotocol.org/soroscan" [ref=e227] [cursor=pointer]:
+ - /url: /webhooks/wh_003
+ - generic [ref=e228]: "CONTRACT: CGHI...F7K1"
+ - cell "VAULT_DEPOSIT YIELD_CLAIMED" [ref=e229]:
+ - generic [ref=e230]:
+ - generic [ref=e231]: VAULT_DEPOSIT
+ - generic [ref=e232]: YIELD_CLAIMED
+ - cell "74.2%" [ref=e233]:
+ - generic [ref=e237]: 74.2%
+ - cell "21/02/2026, 09:10 HTTP 503" [ref=e238]:
+ - text: 21/02/2026, 09:10
+ - generic [ref=e239]: HTTP 503
+ - cell "> DETAIL" [ref=e240]:
+ - generic [ref=e241]:
+ - link "> DETAIL" [ref=e242] [cursor=pointer]:
+ - /url: /webhooks/wh_003
+ - button "> DETAIL" [ref=e243]:
+ - generic [ref=e244]:
+ - generic [ref=e245]: ">"
+ - text: DETAIL
+ - button "Test webhook" [ref=e246]:
+ - img [ref=e247]
+ - button "Delete webhook" [ref=e251]:
+ - img [ref=e252]
+ - row "ACTIVE https://example.com/webhook ALL_EVENTS 100.0% — > DETAIL" [ref=e258]:
+ - cell "ACTIVE" [ref=e259]:
+ - generic [ref=e260]: ACTIVE
+ - cell "https://example.com/webhook" [ref=e262]:
+ - link "https://example.com/webhook" [ref=e264] [cursor=pointer]:
+ - /url: /webhooks/wh_lksbp
+ - cell "ALL_EVENTS" [ref=e265]:
+ - generic [ref=e267]: ALL_EVENTS
+ - cell "100.0%" [ref=e268]:
+ - generic [ref=e272]: 100.0%
+ - cell "—" [ref=e273]
+ - cell "> DETAIL" [ref=e274]:
+ - generic [ref=e275]:
+ - link "> DETAIL" [ref=e276] [cursor=pointer]:
+ - /url: /webhooks/wh_lksbp
+ - button "> DETAIL" [ref=e277]:
+ - generic [ref=e278]:
+ - generic [ref=e279]: ">"
+ - text: DETAIL
+ - button "Test webhook" [disabled] [ref=e280]:
+ - img [ref=e281]
+ - button "Delete webhook" [ref=e285]:
+ - img [ref=e286]
+ - generic [ref=e292]:
+ - generic [ref=e293]:
+ - generic [ref=e294]: SYSTEM_OVERRIDE_ACTIVE
+ - generic [ref=e295]: "AUTH_MODE: DEV_OPEN"
+ - heading "READY_TO_UPLINK?" [level=2] [ref=e296]
+ - paragraph [ref=e297]: Join the decentralised indexing network and fuel your Soroban dApps with high-fidelity event data — free during open beta.
+ - generic [ref=e298]:
+ - link "> GET_API_KEY" [ref=e299] [cursor=pointer]:
+ - /url: /api/docs/
+ - button "> GET_API_KEY" [ref=e300]:
+ - generic [ref=e301]:
+ - generic [ref=e302]: ">"
+ - text: GET_API_KEY
+ - link "> READ_DOCS" [ref=e303] [cursor=pointer]:
+ - /url: /docs
+ - button "> READ_DOCS" [ref=e304]:
+ - generic [ref=e305]:
+ - generic [ref=e306]: ">"
+ - text: READ_DOCS
+ - contentinfo [ref=e307]:
+ - generic [ref=e308]:
+ - generic [ref=e309]:
+ - link "[SOROSCAN]" [ref=e310] [cursor=pointer]:
+ - /url: /
+ - paragraph [ref=e311]: The Graph for Soroban. Real-time event indexing for the Stellar ecosystem.
+ - link "GitHub" [ref=e312] [cursor=pointer]:
+ - /url: https://github.com/SoroScan/soroscan
+ - img [ref=e313]
+ - text: GitHub
+ - generic [ref=e316]:
+ - heading "PRODUCT" [level=3] [ref=e317]
+ - list [ref=e318]:
+ - listitem [ref=e319]:
+ - link "Home" [ref=e320] [cursor=pointer]:
+ - /url: /
+ - listitem [ref=e321]:
+ - link "Features" [ref=e322] [cursor=pointer]:
+ - /url: /features
+ - listitem [ref=e323]:
+ - link "Dashboard" [ref=e324] [cursor=pointer]:
+ - /url: /dashboard
+ - listitem [ref=e325]:
+ - link "Gallery" [ref=e326] [cursor=pointer]:
+ - /url: /gallery
+ - generic [ref=e327]:
+ - heading "DEVELOPERS" [level=3] [ref=e328]
+ - list [ref=e329]:
+ - listitem [ref=e330]:
+ - link "Documentation" [ref=e331] [cursor=pointer]:
+ - /url: /docs
+ - listitem [ref=e332]:
+ - link "API Docs (Swagger)" [ref=e333] [cursor=pointer]:
+ - /url: /api/docs/
+ - listitem [ref=e334]:
+ - link "API Docs (ReDoc)" [ref=e335] [cursor=pointer]:
+ - /url: /api/redoc/
+ - listitem [ref=e336]:
+ - link "SDK — Python" [ref=e337] [cursor=pointer]:
+ - /url: https://github.com/SoroScan/soroscan
+ - listitem [ref=e338]:
+ - link "SDK — TypeScript" [ref=e339] [cursor=pointer]:
+ - /url: https://github.com/SoroScan/soroscan
+ - generic [ref=e340]:
+ - heading "PROJECT" [level=3] [ref=e341]
+ - list [ref=e342]:
+ - listitem [ref=e343]:
+ - link "GitHub" [ref=e344] [cursor=pointer]:
+ - /url: https://github.com/SoroScan/soroscan
+ - listitem [ref=e345]:
+ - link "Contributing" [ref=e346] [cursor=pointer]:
+ - /url: https://github.com/SoroScan/soroscan/blob/main/CONTRIBUTING.md
+ - listitem [ref=e347]:
+ - link "Stellar Network" [ref=e348] [cursor=pointer]:
+ - /url: https://stellar.org
+ - listitem [ref=e349]:
+ - link "Soroban Docs" [ref=e350] [cursor=pointer]:
+ - /url: https://soroban.stellar.org
+ - generic [ref=e351]:
+ - generic [ref=e352]:
+ - generic [ref=e353]: © 2026 SOROSCAN_INDEXER_SERVICES
+ - link "TERMS_OF_SERVICE" [ref=e354] [cursor=pointer]:
+ - /url: "#"
+ - link "PRIVACY_POLICY" [ref=e355] [cursor=pointer]:
+ - /url: "#"
+ - generic [ref=e356]:
+ - generic [ref=e357]: "STELLAR_MAINNET_UPLINK: ONLINE"
+ - generic [ref=e359]: "LATENCY: 42MS"
+ - generic [ref=e360]: ✓WEBHOOK_CREATED — subscription is now active
+ - button "Open Next.js Dev Tools" [ref=e366] [cursor=pointer]:
+ - img [ref=e367]
+ - alert [ref=e371]
+```
\ No newline at end of file
diff --git a/soroscan-frontend/test-results/webhooks-Webhook-Manager-should-create-and-test-a-webhook-firefox/test-failed-1.png b/soroscan-frontend/test-results/webhooks-Webhook-Manager-should-create-and-test-a-webhook-firefox/test-failed-1.png
new file mode 100644
index 000000000..99afd93ad
Binary files /dev/null and b/soroscan-frontend/test-results/webhooks-Webhook-Manager-should-create-and-test-a-webhook-firefox/test-failed-1.png differ
diff --git a/soroscan-frontend/tests/admin.spec.ts b/soroscan-frontend/tests/admin.spec.ts
new file mode 100644
index 000000000..f8577b935
--- /dev/null
+++ b/soroscan-frontend/tests/admin.spec.ts
@@ -0,0 +1,21 @@
+import { test, expect } from '@playwright/test';
+import { setupMocks } from './support/mock-graphql';
+
+test.describe('Admin Dashboard', () => {
+ test.beforeEach(async ({ page }) => {
+ await setupMocks(page);
+ });
+
+ test('admin metrics visibility', async ({ page }) => {
+ await page.goto('/admin');
+
+ // Graceful handling of 404 since admin route is uncertain
+ const is404 = await page.title() === '404' || (await page.locator('h1').innerText()).includes('404');
+ if (is404) {
+ await page.goto('/dashboard');
+ }
+
+ // Potential admin metrics (placeholder)
+ // await expect(page.locator('text=Total Indexers')).toBeVisible();
+ });
+});
diff --git a/soroscan-frontend/tests/auth.spec.ts b/soroscan-frontend/tests/auth.spec.ts
new file mode 100644
index 000000000..0bc246ba8
--- /dev/null
+++ b/soroscan-frontend/tests/auth.spec.ts
@@ -0,0 +1,27 @@
+import { test, expect } from '@playwright/test';
+import { setupMocks } from './support/mock-graphql';
+
+test.describe('Authentication', () => {
+ test.beforeEach(async ({ page }) => {
+ await setupMocks(page);
+ });
+
+ test('login flow', async ({ page }) => {
+ await page.goto('/');
+
+ // Since /login route wasn't found, we assume it's triggered by a button or modal
+ // Common pattern in this UI is GET_API_KEY or similar in the navbar
+ // Use first() to avoid strict mode violations if multiple buttons exist
+ const loginButton = page.getByRole('navigation').getByRole('button', { name: /Login|GET_API_KEY/i }).first();
+
+ if (await loginButton.isVisible()) {
+ await loginButton.click();
+
+ // If it's a modal, fill it (placeholder logic)
+ // await page.getByPlaceholder('email').fill('user@example.com');
+ // await page.getByRole('button', { name: 'Sign In' }).click();
+ } else {
+ test.skip(true, 'Login button not found in current landing page');
+ }
+ });
+});
diff --git a/soroscan-frontend/tests/contracts.spec.ts b/soroscan-frontend/tests/contracts.spec.ts
new file mode 100644
index 000000000..1549ec082
--- /dev/null
+++ b/soroscan-frontend/tests/contracts.spec.ts
@@ -0,0 +1,30 @@
+import { test, expect } from '@playwright/test';
+import { setupMocks } from './support/mock-graphql';
+
+test.describe('Contract Management', () => {
+ test.beforeEach(async ({ page }) => {
+ await setupMocks(page);
+ await page.goto('/contracts');
+ });
+
+ test('should register a new contract', async ({ page }) => {
+ // Wait for page load
+ await expect(page.getByRole('heading', { name: '[CONTRACT_REGISTRY]' })).toBeVisible();
+
+ await page.getByRole('button', { name: 'Register Contract' }).click();
+
+ // Fill the registration modal using placeholders (since label-id link is missing)
+ await page.getByPlaceholder('CA...').fill('CABC1234567890');
+ await page.getByPlaceholder('My Contract').fill('Test Contract');
+
+ // Exact match to avoid collision with "Register Contract" button
+ await page.getByRole('button', { name: 'REGISTER', exact: true }).click();
+
+ // Verify success (Table update)
+ await expect(page.locator('text=Test Contract')).toBeVisible();
+ });
+
+ test('visual regression - contracts page', async ({ page }) => {
+ await expect(page).toHaveScreenshot('contracts.png');
+ });
+});
diff --git a/soroscan-frontend/tests/contracts.spec.ts-snapshots/contracts-chromium-win32.png b/soroscan-frontend/tests/contracts.spec.ts-snapshots/contracts-chromium-win32.png
new file mode 100644
index 000000000..de3753add
Binary files /dev/null and b/soroscan-frontend/tests/contracts.spec.ts-snapshots/contracts-chromium-win32.png differ
diff --git a/soroscan-frontend/tests/contracts.spec.ts-snapshots/contracts-firefox-win32.png b/soroscan-frontend/tests/contracts.spec.ts-snapshots/contracts-firefox-win32.png
new file mode 100644
index 000000000..843a1e1a4
Binary files /dev/null and b/soroscan-frontend/tests/contracts.spec.ts-snapshots/contracts-firefox-win32.png differ
diff --git a/soroscan-frontend/tests/events.spec.ts b/soroscan-frontend/tests/events.spec.ts
new file mode 100644
index 000000000..a7c0ac999
--- /dev/null
+++ b/soroscan-frontend/tests/events.spec.ts
@@ -0,0 +1,50 @@
+import { test, expect } from '@playwright/test';
+import { setupMocks } from './support/mock-graphql';
+
+test.describe('Event Explorer', () => {
+ test.beforeEach(async ({ page }) => {
+ await setupMocks(page);
+ await page.goto('/dashboard');
+ });
+
+ test('should load events and apply filters', async ({ page }) => {
+ await expect(page.getByRole('heading', { name: 'Event Explorer Dashboard' })).toBeVisible();
+
+ const contractDropdown = page.locator('#contract-select');
+
+ // Wait for mock data to populate (should have 2 mock contracts + "All Contracts" = 3 options)
+ await expect(contractDropdown.locator('option')).toHaveCount(3, { timeout: 5000 });
+
+ await contractDropdown.selectOption({ index: 1 });
+
+ // Apply filters
+ await page.getByRole('button', { name: 'Apply Filters' }).click();
+
+ // Verify events load (summary text)
+ await expect(page.locator('text=/Showing/')).toBeVisible({ timeout: 10000 });
+
+ // Test filtering
+ const filterInput = page.getByPlaceholder('Search events...');
+ await filterInput.fill('SWAP');
+
+ // Results should filter client-side
+ const rows = page.locator('tbody tr');
+ await expect(rows).toHaveCount(1); // Mock data has one SWAP event
+ });
+
+ test('should export events as CSV', async ({ page }) => {
+ const contractDropdown = page.locator('#contract-select');
+ await expect(contractDropdown.locator('option')).toHaveCount(3, { timeout: 5000 });
+ await contractDropdown.selectOption({ index: 1 });
+
+ const downloadPromise = page.waitForEvent('download');
+ await page.getByRole('button', { name: 'Export CSV' }).click();
+
+ const download = await downloadPromise;
+ expect(download.suggestedFilename()).toContain('.csv');
+ });
+
+ test('visual regression - dashboard', async ({ page }) => {
+ await expect(page).toHaveScreenshot('dashboard.png');
+ });
+});
diff --git a/soroscan-frontend/tests/events.spec.ts-snapshots/dashboard-chromium-win32.png b/soroscan-frontend/tests/events.spec.ts-snapshots/dashboard-chromium-win32.png
new file mode 100644
index 000000000..fd917b0f2
Binary files /dev/null and b/soroscan-frontend/tests/events.spec.ts-snapshots/dashboard-chromium-win32.png differ
diff --git a/soroscan-frontend/tests/events.spec.ts-snapshots/dashboard-firefox-win32.png b/soroscan-frontend/tests/events.spec.ts-snapshots/dashboard-firefox-win32.png
new file mode 100644
index 000000000..e4d9438ea
Binary files /dev/null and b/soroscan-frontend/tests/events.spec.ts-snapshots/dashboard-firefox-win32.png differ
diff --git a/soroscan-frontend/tests/support/mock-graphql.ts b/soroscan-frontend/tests/support/mock-graphql.ts
new file mode 100644
index 000000000..71cc828be
--- /dev/null
+++ b/soroscan-frontend/tests/support/mock-graphql.ts
@@ -0,0 +1,93 @@
+import { Page } from '@playwright/test';
+
+export async function setupMocks(page: Page) {
+ await page.route('**/api/graphql', async (route) => {
+ const request = route.request();
+ const postData = request.postDataJSON();
+ const query = postData?.query || '';
+ const operationName = postData?.operationName;
+
+ // Handle different GraphQL queries based on content or operationName
+ if (query.includes('AllContracts')) {
+ return route.fulfill({
+ status: 200,
+ contentType: 'application/json',
+ body: JSON.stringify({
+ data: {
+ contracts: [
+ { contractId: 'CABC1234567890', name: 'Test Token' },
+ { contractId: 'CDEF0987654321', name: 'Liquidity Pool' }
+ ]
+ }
+ }),
+ });
+ }
+
+ if (query.includes('EventTypes')) {
+ return route.fulfill({
+ status: 200,
+ contentType: 'application/json',
+ body: JSON.stringify({
+ data: {
+ eventTypes: ['SWAP', 'MINT', 'BURN', 'TRANSFER']
+ }
+ }),
+ });
+ }
+
+ if (query.includes('ExplorerEvents') || query.includes('AllEvents')) {
+ return route.fulfill({
+ status: 200,
+ contentType: 'application/json',
+ body: JSON.stringify({
+ data: {
+ events: [
+ {
+ id: 'ev_1',
+ eventType: 'SWAP',
+ ledger: 1001,
+ eventIndex: 0,
+ timestamp: new Date().toISOString(),
+ txHash: '0x123...abc',
+ payload: { amount: '100', token: 'XLM' },
+ contractId: 'CABC1234567890',
+ contractName: 'Test Token'
+ },
+ {
+ id: 'ev_2',
+ eventType: 'TRANSFER',
+ ledger: 1002,
+ eventIndex: 1,
+ timestamp: new Date().toISOString(),
+ txHash: '0x456...def',
+ payload: { from: 'addr1', to: 'addr2', amount: '50' },
+ contractId: 'CABC1234567890',
+ contractName: 'Test Token'
+ }
+ ],
+ allEvents: [
+ {
+ id: 'ev_1',
+ eventType: 'SWAP',
+ ledger: 1001,
+ eventIndex: 0,
+ timestamp: new Date().toISOString(),
+ txHash: '0x123...abc',
+ payload: { amount: '100', token: 'XLM' },
+ contractId: 'CABC1234567890',
+ contractName: 'Test Token'
+ }
+ ]
+ }
+ }),
+ });
+ }
+
+ // Default response for other queries
+ return route.fulfill({
+ status: 200,
+ contentType: 'application/json',
+ body: JSON.stringify({ data: {} }),
+ });
+ });
+}
diff --git a/soroscan-frontend/tests/webhooks.spec.ts b/soroscan-frontend/tests/webhooks.spec.ts
new file mode 100644
index 000000000..82d0bef3e
--- /dev/null
+++ b/soroscan-frontend/tests/webhooks.spec.ts
@@ -0,0 +1,32 @@
+import { test, expect } from '@playwright/test';
+import { setupMocks } from './support/mock-graphql';
+
+test.describe('Webhook Manager', () => {
+ test.beforeEach(async ({ page }) => {
+ await setupMocks(page);
+ await page.goto('/webhooks');
+ });
+
+ test('should create and test a webhook', async ({ page }) => {
+ await expect(page.getByRole('heading', { name: 'SUBSCRIPTIONS' })).toBeVisible();
+
+ await page.getByRole('button', { name: 'NEW_WEBHOOK' }).click();
+
+ // Fill the webhook modal using placeholder
+ await page.getByPlaceholder('https://yourapp.io/webhook').fill('https://example.com/webhook');
+ await page.getByRole('button', { name: 'CREATE_WEBHOOK' }).click();
+
+ // Verify in table
+ await expect(page.locator('text=https://example.com/webhook')).toBeVisible();
+
+ // Test the webhook (simulated)
+ await page.locator('tr').filter({ hasText: 'https://example.com/webhook' }).getByRole('button', { name: 'TEST' }).click();
+
+ // Wait for test result (UI shows "OK" after simulation)
+ await expect(page.locator('text=OK')).toBeVisible({ timeout: 5000 });
+ });
+
+ test('visual regression - webhooks page', async ({ page }) => {
+ await expect(page).toHaveScreenshot('webhooks.png');
+ });
+});
diff --git a/soroscan-frontend/tests/webhooks.spec.ts-snapshots/webhooks-chromium-win32.png b/soroscan-frontend/tests/webhooks.spec.ts-snapshots/webhooks-chromium-win32.png
new file mode 100644
index 000000000..423ff097a
Binary files /dev/null and b/soroscan-frontend/tests/webhooks.spec.ts-snapshots/webhooks-chromium-win32.png differ
diff --git a/soroscan-frontend/tests/webhooks.spec.ts-snapshots/webhooks-firefox-win32.png b/soroscan-frontend/tests/webhooks.spec.ts-snapshots/webhooks-firefox-win32.png
new file mode 100644
index 000000000..1aa4f5599
Binary files /dev/null and b/soroscan-frontend/tests/webhooks.spec.ts-snapshots/webhooks-firefox-win32.png differ