Skip to content

Commit fa122e8

Browse files
authored
Merge branch 'main' into feat-breadcrumbing-navigation
2 parents 2a59f59 + 38760e8 commit fa122e8

143 files changed

Lines changed: 31817 additions & 1711 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

README.md

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,16 @@ Rust-based smart contracts deployed on **Stellar Testnet** via Soroban. Features
3939
Express.js API server providing:
4040

4141
- **AI Work Verification** — Validates freelancer deliverables against project requirements using AI
42+
- **Bulk Verification Operations** — Batch verify, update, and delete verification records
4243
- **AI Invoice Generation** — Automated invoice creation for completed work
4344
- **Stellar Horizon Integration** — On-chain payment status and transaction lookups
45+
- **Scheduled Jobs** — Cron-like tasks for background maintenance and monitoring
46+
47+
### Bulk Verification Endpoints
48+
49+
- `POST /api/v1/verification/verify/batch`
50+
- `PATCH /api/v1/verification/batch`
51+
- `DELETE /api/v1/verification/batch`
4452

4553
## Features
4654

@@ -95,6 +103,43 @@ soroban contract deploy --wasm target/wasm32-unknown-unknown/release/agenticpay.
95103
| `NEXT_PUBLIC_STELLAR_NETWORK` | `testnet` or `public` |
96104
| `OPENAI_API_KEY` | OpenAI API key for AI verification |
97105
| `STELLAR_SECRET_KEY` | Server-side Stellar signing key |
106+
| `JOBS_ENABLED` | Set to `false` to disable scheduled jobs |
107+
108+
### Scheduled Jobs
109+
110+
- Default jobs live under `backend/src/jobs`
111+
- Job status endpoint: `GET /api/v1/jobs`
112+
113+
## Contract Verification
114+
115+
The AgenticPay smart contract source code is published for on-chain verification. To verify the deployed contract matches the source:
116+
117+
### Build the contract from source
118+
119+
```bash
120+
cd contracts
121+
cargo build --target wasm32-unknown-unknown --release
122+
```
123+
124+
### Verify the WASM hash matches the deployed contract
125+
126+
```bash
127+
# Get the on-chain WASM hash
128+
soroban contract inspect --id $NEXT_PUBLIC_CONTRACT_ID --network testnet
129+
130+
# Compute the local WASM hash
131+
sha256sum target/wasm32-unknown-unknown/release/agenticpay.wasm
132+
```
133+
134+
The SHA-256 hash of the locally compiled WASM should match the on-chain contract hash, confirming the deployed bytecode was produced from this source.
135+
136+
### Verification status
137+
138+
| Network | Contract ID | Status |
139+
|---------|-------------|--------|
140+
| Testnet | See `NEXT_PUBLIC_CONTRACT_ID` in `.env` | Source published |
141+
142+
> **Note:** Deterministic builds require the same Rust toolchain version. See `contracts/Cargo.toml` for the SDK version and use `rust-toolchain.toml` if present.
98143
99144
## Network
100145

backend/frontend/.gitignore

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2+
3+
# dependencies
4+
/node_modules
5+
/.pnp
6+
.pnp.*
7+
.yarn/*
8+
!.yarn/patches
9+
!.yarn/plugins
10+
!.yarn/releases
11+
!.yarn/versions
12+
13+
# testing
14+
/coverage
15+
16+
# next.js
17+
/.next/
18+
/out/
19+
20+
# production
21+
/build
22+
23+
# misc
24+
.DS_Store
25+
*.pem
26+
27+
# debug
28+
npm-debug.log*
29+
yarn-debug.log*
30+
yarn-error.log*
31+
.pnpm-debug.log*
32+
33+
# env files (can opt-in for committing if needed)
34+
.env*
35+
36+
# vercel
37+
.vercel
38+
39+
# typescript
40+
*.tsbuildinfo
41+
next-env.d.ts

backend/frontend/README.md

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-next-app`](https://nextjs.org/docs/app/api-reference/cli/create-next-app).
2+
3+
## Getting Started
4+
5+
First, run the development server:
6+
7+
```bash
8+
npm run dev
9+
# or
10+
yarn dev
11+
# or
12+
pnpm dev
13+
# or
14+
bun dev
15+
```
16+
17+
Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
18+
19+
You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file.
20+
21+
This project uses [`next/font`](https://nextjs.org/docs/app/building-your-application/optimizing/fonts) to automatically optimize and load [Geist](https://vercel.com/font), a new font family for Vercel.
22+
23+
## Learn More
24+
25+
To learn more about Next.js, take a look at the following resources:
26+
27+
- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
28+
- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.
29+
30+
You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js) - your feedback and contributions are welcome!
31+
32+
## Deploy on Vercel
33+
34+
The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.
35+
36+
Check out our [Next.js deployment documentation](https://nextjs.org/docs/app/building-your-application/deploying) for more details.

backend/frontend/app/auth/page.tsx

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
'use client';
2+
3+
import { motion } from 'framer-motion';
4+
import { SocialLogin } from '@/components/auth/SocialLogin';
5+
import { WalletConnect } from '@/components/auth/WalletConnect';
6+
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs';
7+
import { Wallet, Users } from 'lucide-react';
8+
9+
export default function AuthPage() {
10+
return (
11+
<div className="min-h-screen flex items-center justify-center bg-gradient-to-br from-blue-50 via-white to-purple-50 p-4">
12+
<motion.div
13+
initial={{ opacity: 0, y: 20 }}
14+
animate={{ opacity: 1, y: 0 }}
15+
transition={{ duration: 0.5 }}
16+
className="w-full max-w-md"
17+
>
18+
<div className="bg-white rounded-2xl shadow-xl p-8">
19+
<div className="text-center mb-8">
20+
<motion.div
21+
initial={{ scale: 0 }}
22+
animate={{ scale: 1 }}
23+
transition={{ delay: 0.2, type: 'spring' }}
24+
className="inline-flex items-center justify-center w-16 h-16 rounded-full bg-gradient-to-r from-blue-600 to-purple-600 mb-4"
25+
>
26+
<Wallet className="h-8 w-8 text-white" />
27+
</motion.div>
28+
<h1 className="text-3xl font-bold text-gray-900 mb-2">
29+
Welcome to AgenticPay
30+
</h1>
31+
<p className="text-gray-600">
32+
Get paid instantly for your work
33+
</p>
34+
</div>
35+
36+
<Tabs defaultValue="social" className="w-full">
37+
<TabsList className="grid w-full grid-cols-2 mb-6">
38+
<TabsTrigger value="social" className="flex items-center gap-2">
39+
<Users className="h-4 w-4" />
40+
Social Login
41+
</TabsTrigger>
42+
<TabsTrigger value="wallet" className="flex items-center gap-2">
43+
<Wallet className="h-4 w-4" />
44+
Web3 Wallet
45+
</TabsTrigger>
46+
</TabsList>
47+
48+
<TabsContent value="social">
49+
<SocialLogin />
50+
</TabsContent>
51+
52+
<TabsContent value="wallet">
53+
<WalletConnect />
54+
</TabsContent>
55+
</Tabs>
56+
57+
<p className="text-xs text-gray-500 text-center mt-6">
58+
By continuing, you agree to our Terms of Service and Privacy Policy
59+
</p>
60+
</div>
61+
</motion.div>
62+
</div>
63+
);
64+
}
65+
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
'use client';
2+
3+
import { useParams } from 'next/navigation';
4+
import { useAgenticPay } from '@/lib/hooks/useAgenticPay';
5+
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
6+
import { Button } from '@/components/ui/button';
7+
import { ArrowLeft, ExternalLink, Download } from 'lucide-react';
8+
import Link from 'next/link';
9+
import { Skeleton } from '@/components/ui/skeleton';
10+
11+
export default function InvoiceDetailPage() {
12+
const params = useParams();
13+
const rawId = params.id as string;
14+
const projectId = rawId.startsWith('INV-') ? rawId.replace('INV-', '') : rawId;
15+
16+
const { useProjectDetail } = useAgenticPay();
17+
const { project, loading } = useProjectDetail(projectId);
18+
19+
if (loading) {
20+
return (
21+
<div className="space-y-6">
22+
<Skeleton className="h-10 w-32" />
23+
<Card>
24+
<CardHeader>
25+
<Skeleton className="h-8 w-64 mb-2" />
26+
</CardHeader>
27+
<CardContent className="space-y-6">
28+
<Skeleton className="h-32 w-full" />
29+
</CardContent>
30+
</Card>
31+
</div>
32+
);
33+
}
34+
35+
if (!project || (!project.invoiceUri && project.status !== 'completed')) {
36+
return (
37+
<div className="flex flex-col items-center justify-center h-64">
38+
<p className="text-gray-600 mb-4">Invoice not found</p>
39+
<Link href="/dashboard/invoices">
40+
<Button>Back to Invoices</Button>
41+
</Link>
42+
</div>
43+
);
44+
}
45+
46+
// Construct display status
47+
const status = project.status === 'completed' ? 'paid' : 'pending';
48+
49+
return (
50+
<div className="space-y-6">
51+
<Link href="/dashboard/invoices">
52+
<Button variant="ghost" className="mb-4">
53+
<ArrowLeft className="h-4 w-4 mr-2" />
54+
Back to Invoices
55+
</Button>
56+
</Link>
57+
58+
<Card>
59+
<CardHeader>
60+
<div className="flex justify-between items-start">
61+
<div>
62+
<CardTitle className="text-2xl mb-2">Invoice #{rawId}</CardTitle>
63+
<p className="text-gray-600">{project.title}</p>
64+
</div>
65+
<span
66+
className={`px-4 py-2 rounded-full text-sm font-medium ${status === 'paid'
67+
? 'bg-green-100 text-green-700'
68+
: 'bg-yellow-100 text-yellow-700'
69+
}`}
70+
>
71+
{status.toUpperCase()}
72+
</span>
73+
</div>
74+
</CardHeader>
75+
<CardContent className="space-y-6">
76+
<div className="grid grid-cols-2 gap-6">
77+
<div>
78+
<p className="text-sm text-gray-600 mb-1">Amount</p>
79+
<p className="text-2xl font-bold">
80+
{project.totalAmount} {project.currency}
81+
</p>
82+
</div>
83+
<div>
84+
<p className="text-sm text-gray-600 mb-1">Milestone</p>
85+
<p className="text-lg font-medium">Full Project</p>
86+
</div>
87+
</div>
88+
89+
<div className="border-t pt-6 space-y-4">
90+
<div>
91+
<p className="text-sm text-gray-600 mb-2">Client</p>
92+
<p className="font-medium">{project.client.name}</p>
93+
<p className="text-sm text-gray-500 font-mono">{project.client.address}</p>
94+
</div>
95+
<div>
96+
<p className="text-sm text-gray-600 mb-2">Freelancer</p>
97+
<p className="font-medium">{project.freelancer.name}</p>
98+
<p className="text-sm text-gray-500 font-mono">{project.freelancer.address}</p>
99+
</div>
100+
</div>
101+
102+
<div className="border-t pt-6 space-y-2">
103+
<div className="flex justify-between text-sm">
104+
<span className="text-gray-600">Generated</span>
105+
<span className="font-medium">
106+
{new Date(project.createdAt).toLocaleString()}
107+
</span>
108+
</div>
109+
</div>
110+
111+
<div className="flex gap-3 pt-4">
112+
<Button variant="outline">
113+
<Download className="h-4 w-4 mr-2" />
114+
Download PDF
115+
</Button>
116+
</div>
117+
</CardContent>
118+
</Card>
119+
</div>
120+
);
121+
}

0 commit comments

Comments
 (0)