strade-stx 1.0.0 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (104) hide show
  1. package/package.json +10 -1
  2. package/contracts/CoreMarketPlace.clar +0 -227
  3. package/contracts/DisputeResolution_clar.clar +0 -265
  4. package/contracts/EscrowService.clar +0 -171
  5. package/contracts/UserProfile.clar +0 -280
  6. package/contracts/ft-trait.clar +0 -24
  7. package/contracts/token.clar +0 -178
  8. package/frontend/README.md +0 -10
  9. package/frontend/components.json +0 -22
  10. package/frontend/dist/assets/index-BacuuL66.css +0 -1
  11. package/frontend/dist/assets/index-jryypd5B.js +0 -194
  12. package/frontend/dist/favicon.png +0 -0
  13. package/frontend/dist/index.html +0 -15
  14. package/frontend/dist/manifest.json +0 -15
  15. package/frontend/dist/vite.svg +0 -1
  16. package/frontend/empty-mock.js +0 -1
  17. package/frontend/eslint.config.js +0 -23
  18. package/frontend/eslint.config.mjs +0 -25
  19. package/frontend/index.html +0 -14
  20. package/frontend/next.config.ts +0 -17
  21. package/frontend/package-lock.json +0 -14740
  22. package/frontend/package.json +0 -56
  23. package/frontend/postcss.config.js +0 -5
  24. package/frontend/postcss.config.mjs +0 -5
  25. package/frontend/public/favicon.png +0 -0
  26. package/frontend/public/file.svg +0 -1
  27. package/frontend/public/globe.svg +0 -1
  28. package/frontend/public/manifest.json +0 -15
  29. package/frontend/public/next.svg +0 -1
  30. package/frontend/public/vercel.svg +0 -1
  31. package/frontend/public/vite.svg +0 -1
  32. package/frontend/public/window.svg +0 -1
  33. package/frontend/src/App.css +0 -42
  34. package/frontend/src/App.tsx +0 -177
  35. package/frontend/src/app/about/page.tsx +0 -208
  36. package/frontend/src/app/favicon.ico +0 -0
  37. package/frontend/src/app/globals.css +0 -129
  38. package/frontend/src/app/help/page.tsx +0 -167
  39. package/frontend/src/app/how-it-works/page.tsx +0 -274
  40. package/frontend/src/app/layout.tsx +0 -55
  41. package/frontend/src/app/marketplace/page.tsx +0 -324
  42. package/frontend/src/app/my-listings/page.tsx +0 -318
  43. package/frontend/src/app/page.tsx +0 -15
  44. package/frontend/src/assets/react.svg +0 -1
  45. package/frontend/src/components/ConfirmDialog.tsx +0 -54
  46. package/frontend/src/components/CreateListingForm.tsx +0 -231
  47. package/frontend/src/components/ErrorBoundary.tsx +0 -73
  48. package/frontend/src/components/FilterPanel.tsx +0 -10
  49. package/frontend/src/components/Footer.tsx +0 -100
  50. package/frontend/src/components/Header.tsx +0 -268
  51. package/frontend/src/components/ImageUpload.tsx +0 -147
  52. package/frontend/src/components/LandingPage.tsx +0 -322
  53. package/frontend/src/components/ListingCard.tsx +0 -154
  54. package/frontend/src/components/LoadingSkeleton.tsx +0 -44
  55. package/frontend/src/components/MobileNav.tsx +0 -89
  56. package/frontend/src/components/NotificationBell.tsx +0 -8
  57. package/frontend/src/components/NotificationPanel.tsx +0 -14
  58. package/frontend/src/components/README.md +0 -14
  59. package/frontend/src/components/SearchBar.tsx +0 -10
  60. package/frontend/src/components/TestnetBanner.tsx +0 -29
  61. package/frontend/src/components/ThemeToggle.tsx +0 -32
  62. package/frontend/src/components/__tests__/Header.test.tsx +0 -70
  63. package/frontend/src/components/__tests__/ListingCard.test.tsx +0 -86
  64. package/frontend/src/components/providers/ThemeProvider.tsx +0 -9
  65. package/frontend/src/components/ui/alert-dialog.tsx +0 -141
  66. package/frontend/src/components/ui/avatar.tsx +0 -53
  67. package/frontend/src/components/ui/badge.tsx +0 -46
  68. package/frontend/src/components/ui/button.tsx +0 -60
  69. package/frontend/src/components/ui/card.tsx +0 -92
  70. package/frontend/src/components/ui/dialog.tsx +0 -143
  71. package/frontend/src/components/ui/dropdown-menu.tsx +0 -257
  72. package/frontend/src/components/ui/input.tsx +0 -21
  73. package/frontend/src/components/ui/label.tsx +0 -24
  74. package/frontend/src/components/ui/select.tsx +0 -187
  75. package/frontend/src/components/ui/sonner.tsx +0 -40
  76. package/frontend/src/components/ui/textarea.tsx +0 -18
  77. package/frontend/src/context/README.md +0 -27
  78. package/frontend/src/index.css +0 -166
  79. package/frontend/src/lib/notificationEvents.ts +0 -10
  80. package/frontend/src/lib/notificationStore.ts +0 -13
  81. package/frontend/src/lib/notifications.ts +0 -13
  82. package/frontend/src/lib/search.ts +0 -28
  83. package/frontend/src/lib/stacks.ts +0 -189
  84. package/frontend/src/lib/utils.ts +0 -6
  85. package/frontend/src/main.tsx +0 -10
  86. package/frontend/src/test/setup.ts +0 -23
  87. package/frontend/src/types.d.ts +0 -9
  88. package/frontend/tsconfig.app.json +0 -28
  89. package/frontend/tsconfig.json +0 -41
  90. package/frontend/tsconfig.node.json +0 -26
  91. package/frontend/vercel.json +0 -4
  92. package/frontend/vite.config.ts +0 -6
  93. package/frontend/vitest.config.ts +0 -17
  94. package/scripts/auto-activity.sh +0 -9
  95. package/scripts/cancel-pending.ts +0 -67
  96. package/scripts/check-balances.ts +0 -23
  97. package/scripts/distribute-evenly.ts +0 -56
  98. package/scripts/drain-accounts.ts +0 -70
  99. package/scripts/fund-accounts.ts +0 -88
  100. package/scripts/fund-active.ts +0 -59
  101. package/scripts/fund-unfunded.ts +0 -88
  102. package/scripts/generate-activity.ts +0 -181
  103. package/scripts/git-activity-generator.ts +0 -154
  104. package/scripts/mobile-server.ts +0 -123
@@ -1,54 +0,0 @@
1
- 'use client';
2
-
3
- import {
4
- AlertDialog,
5
- AlertDialogAction,
6
- AlertDialogCancel,
7
- AlertDialogContent,
8
- AlertDialogDescription,
9
- AlertDialogFooter,
10
- AlertDialogHeader,
11
- AlertDialogTitle,
12
- } from '@/components/ui/alert-dialog';
13
-
14
- interface ConfirmDialogProps {
15
- open: boolean;
16
- onOpenChange: (open: boolean) => void;
17
- title: string;
18
- description: string;
19
- onConfirm: () => void;
20
- confirmText?: string;
21
- cancelText?: string;
22
- destructive?: boolean;
23
- }
24
-
25
- export default function ConfirmDialog({
26
- open,
27
- onOpenChange,
28
- title,
29
- description,
30
- onConfirm,
31
- confirmText = 'Confirm',
32
- cancelText = 'Cancel',
33
- destructive = false,
34
- }: ConfirmDialogProps) {
35
- return (
36
- <AlertDialog open={open} onOpenChange={onOpenChange}>
37
- <AlertDialogContent>
38
- <AlertDialogHeader>
39
- <AlertDialogTitle>{title}</AlertDialogTitle>
40
- <AlertDialogDescription>{description}</AlertDialogDescription>
41
- </AlertDialogHeader>
42
- <AlertDialogFooter>
43
- <AlertDialogCancel>{cancelText}</AlertDialogCancel>
44
- <AlertDialogAction
45
- onClick={onConfirm}
46
- className={destructive ? 'bg-red-600 hover:bg-red-700' : ''}
47
- >
48
- {confirmText}
49
- </AlertDialogAction>
50
- </AlertDialogFooter>
51
- </AlertDialogContent>
52
- </AlertDialog>
53
- );
54
- }
@@ -1,231 +0,0 @@
1
- 'use client';
2
-
3
- import { useState } from 'react';
4
- import { Button } from '@/components/ui/button';
5
- import { Input } from '@/components/ui/input';
6
- import { Label } from '@/components/ui/label';
7
- import { Textarea } from '@/components/ui/textarea';
8
- import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogTrigger } from '@/components/ui/dialog';
9
- import ImageUpload from '@/components/ImageUpload';
10
- import { Plus } from 'lucide-react';
11
-
12
- interface CreateListingFormProps {
13
- onCreateListing?: (data: {
14
- name: string;
15
- description: string;
16
- price: number;
17
- duration: number;
18
- imageUrl?: string;
19
- }) => void;
20
- }
21
-
22
- export default function CreateListingForm({ onCreateListing }: CreateListingFormProps) {
23
- const [isOpen, setIsOpen] = useState(false);
24
- const [isSubmitting, setIsSubmitting] = useState(false);
25
- const [errors, setErrors] = useState<Record<string, string>>({});
26
- const [formData, setFormData] = useState({
27
- name: '',
28
- description: '',
29
- price: '',
30
- duration: '',
31
- imageUrl: '',
32
- });
33
-
34
- const validateForm = (): boolean => {
35
- const newErrors: Record<string, string> = {};
36
-
37
- if (!formData.name.trim()) {
38
- newErrors.name = 'Item name is required';
39
- } else if (formData.name.length < 3) {
40
- newErrors.name = 'Item name must be at least 3 characters';
41
- } else if (formData.name.length > 64) {
42
- newErrors.name = 'Item name must be less than 64 characters';
43
- }
44
-
45
- if (!formData.description.trim()) {
46
- newErrors.description = 'Description is required';
47
- } else if (formData.description.length < 10) {
48
- newErrors.description = 'Description must be at least 10 characters';
49
- } else if (formData.description.length > 256) {
50
- newErrors.description = 'Description must be less than 256 characters';
51
- }
52
-
53
- const price = parseFloat(formData.price);
54
- if (!formData.price || isNaN(price)) {
55
- newErrors.price = 'Valid price is required';
56
- } else if (price <= 0) {
57
- newErrors.price = 'Price must be greater than 0';
58
- } else if (price > 1000000) {
59
- newErrors.price = 'Price is too high';
60
- }
61
-
62
- const duration = parseInt(formData.duration);
63
- if (!formData.duration || isNaN(duration)) {
64
- newErrors.duration = 'Valid duration is required';
65
- } else if (duration < 1) {
66
- newErrors.duration = 'Duration must be at least 1 day';
67
- } else if (duration > 365) {
68
- newErrors.duration = 'Duration cannot exceed 365 days';
69
- }
70
-
71
- setErrors(newErrors);
72
- return Object.keys(newErrors).length === 0;
73
- };
74
-
75
- const handleSubmit = async (e: React.FormEvent) => {
76
- e.preventDefault();
77
-
78
- if (!validateForm()) return;
79
- if (!onCreateListing) return;
80
-
81
- setIsSubmitting(true);
82
- try {
83
- const price = parseFloat(formData.price) * 1000000; // Convert to microSTX
84
- const duration = parseInt(formData.duration) * 144; // Convert days to blocks (approx 10 min per block)
85
-
86
- await onCreateListing({
87
- name: formData.name,
88
- description: formData.description,
89
- price,
90
- duration,
91
- imageUrl: formData.imageUrl,
92
- });
93
-
94
- // Reset form and close dialog
95
- setFormData({ name: '', description: '', price: '', duration: '', imageUrl: '' });
96
- setErrors({});
97
- setIsOpen(false);
98
- } catch (error) {
99
- console.error('Error creating listing:', error);
100
- } finally {
101
- setIsSubmitting(false);
102
- }
103
- };
104
-
105
- const handleInputChange = (field: string, value: string) => {
106
- setFormData(prev => ({ ...prev, [field]: value }));
107
- // Clear error for this field when user starts typing
108
- if (errors[field]) {
109
- setErrors(prev => ({ ...prev, [field]: '' }));
110
- }
111
- };
112
-
113
- return (
114
- <Dialog open={isOpen} onOpenChange={setIsOpen}>
115
- <DialogTrigger asChild>
116
- <Button className="mb-6">
117
- <Plus className="h-4 w-4 mr-2" />
118
- Create Listing
119
- </Button>
120
- </DialogTrigger>
121
-
122
- <DialogContent className="sm:max-w-[500px]">
123
- <DialogHeader>
124
- <DialogTitle>Create New Listing</DialogTitle>
125
- </DialogHeader>
126
-
127
- <form onSubmit={handleSubmit} className="space-y-4">
128
- <div>
129
- <Label>Item Image (Optional)</Label>
130
- <ImageUpload
131
- onImageSelect={(url) => handleInputChange('imageUrl', url)}
132
- currentImage={formData.imageUrl}
133
- />
134
- <p className="text-xs text-slate-500 mt-1">
135
- Add an image to make your listing more attractive
136
- </p>
137
- </div>
138
-
139
- <div>
140
- <Label htmlFor="name">Item Name *</Label>
141
- <Input
142
- id="name"
143
- value={formData.name}
144
- onChange={(e) => handleInputChange('name', e.target.value)}
145
- placeholder="Enter item name"
146
- maxLength={64}
147
- className={errors.name ? 'border-red-500' : ''}
148
- />
149
- {errors.name && (
150
- <p className="text-xs text-red-500 mt-1">{errors.name}</p>
151
- )}
152
- </div>
153
-
154
- <div>
155
- <Label htmlFor="description">Description *</Label>
156
- <Textarea
157
- id="description"
158
- value={formData.description}
159
- onChange={(e) => handleInputChange('description', e.target.value)}
160
- placeholder="Describe your item"
161
- maxLength={256}
162
- rows={3}
163
- className={errors.description ? 'border-red-500' : ''}
164
- />
165
- {errors.description && (
166
- <p className="text-xs text-red-500 mt-1">{errors.description}</p>
167
- )}
168
- <p className="text-xs text-slate-500 mt-1">
169
- {formData.description.length}/256 characters
170
- </p>
171
- </div>
172
-
173
- <div className="grid grid-cols-2 gap-4">
174
- <div>
175
- <Label htmlFor="price">Price (STX) *</Label>
176
- <Input
177
- id="price"
178
- type="number"
179
- step="0.000001"
180
- min="0"
181
- value={formData.price}
182
- onChange={(e) => handleInputChange('price', e.target.value)}
183
- placeholder="0.00"
184
- className={errors.price ? 'border-red-500' : ''}
185
- />
186
- {errors.price && (
187
- <p className="text-xs text-red-500 mt-1">{errors.price}</p>
188
- )}
189
- </div>
190
-
191
- <div>
192
- <Label htmlFor="duration">Duration (days) *</Label>
193
- <Input
194
- id="duration"
195
- type="number"
196
- min="1"
197
- max="365"
198
- value={formData.duration}
199
- onChange={(e) => handleInputChange('duration', e.target.value)}
200
- placeholder="30"
201
- className={errors.duration ? 'border-red-500' : ''}
202
- />
203
- {errors.duration && (
204
- <p className="text-xs text-red-500 mt-1">{errors.duration}</p>
205
- )}
206
- </div>
207
- </div>
208
-
209
- <div className="flex justify-end space-x-2 pt-4">
210
- <Button
211
- type="button"
212
- variant="outline"
213
- onClick={() => setIsOpen(false)}
214
- disabled={isSubmitting}
215
- >
216
- Cancel
217
- </Button>
218
- <Button type="submit" disabled={isSubmitting}>
219
- {isSubmitting ? 'Creating...' : 'Create Listing'}
220
- </Button>
221
- </div>
222
- </form>
223
- </DialogContent>
224
- </Dialog>
225
- );
226
- }
227
- // w-full
228
- // flex-col
229
- // h-12
230
- // font-size: 16px
231
- // modal overflow
@@ -1,73 +0,0 @@
1
- 'use client';
2
-
3
- import React from 'react';
4
- import { Button } from '@/components/ui/button';
5
- import { AlertCircle } from 'lucide-react';
6
-
7
- interface ErrorBoundaryProps {
8
- children: React.ReactNode;
9
- }
10
-
11
- interface ErrorBoundaryState {
12
- hasError: boolean;
13
- error?: Error;
14
- }
15
-
16
- export class ErrorBoundary extends React.Component<ErrorBoundaryProps, ErrorBoundaryState> {
17
- constructor(props: ErrorBoundaryProps) {
18
- super(props);
19
- this.state = { hasError: false };
20
- }
21
-
22
- static getDerivedStateFromError(error: Error): ErrorBoundaryState {
23
- return { hasError: true, error };
24
- }
25
-
26
- componentDidCatch(error: Error, errorInfo: React.ErrorInfo) {
27
- console.error('Error caught by boundary:', error, errorInfo);
28
- }
29
-
30
- render() {
31
- if (this.state.hasError) {
32
- return (
33
- <div className="min-h-screen bg-slate-50 flex items-center justify-center p-4">
34
- <div className="max-w-md w-full bg-white rounded-lg shadow-lg p-8 text-center">
35
- <div className="mb-6">
36
- <div className="mx-auto w-16 h-16 bg-red-100 rounded-full flex items-center justify-center">
37
- <AlertCircle className="h-8 w-8 text-red-600" />
38
- </div>
39
- </div>
40
-
41
- <h1 className="text-2xl font-bold text-slate-900 mb-2">
42
- Something went wrong
43
- </h1>
44
-
45
- <p className="text-slate-600 mb-6">
46
- We encountered an unexpected error. Please try refreshing the page.
47
- </p>
48
-
49
- {this.state.error && (
50
- <details className="text-left mb-6 p-4 bg-slate-50 rounded text-sm">
51
- <summary className="cursor-pointer font-medium text-slate-700 mb-2">
52
- Error details
53
- </summary>
54
- <pre className="text-xs text-slate-600 overflow-auto">
55
- {this.state.error.toString()}
56
- </pre>
57
- </details>
58
- )}
59
-
60
- <Button
61
- onClick={() => window.location.reload()}
62
- className="w-full"
63
- >
64
- Refresh Page
65
- </Button>
66
- </div>
67
- </div>
68
- );
69
- }
70
-
71
- return this.props.children;
72
- }
73
- }
@@ -1,10 +0,0 @@
1
- // FilterPanel
2
- // min/max price
3
- // status select
4
- // category
5
- // reset
6
- // apply
7
- // badge
8
- // collapse
9
- // URL params
10
- // reset page
@@ -1,100 +0,0 @@
1
- import Link from 'next/link';
2
- import { Github, ExternalLink } from 'lucide-react';
3
-
4
- export default function Footer() {
5
- return (
6
- <footer className="bg-gray-50 dark:bg-gray-950 border-t border-gray-200 dark:border-gray-800 mt-16">
7
- <div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
8
- <div className="grid grid-cols-1 md:grid-cols-3 gap-8">
9
- <div>
10
- <h3 className="text-lg font-semibold text-black dark:text-white mb-4">Strade</h3>
11
- <p className="text-gray-600 dark:text-gray-400 text-sm">
12
- A decentralized marketplace built on Stacks blockchain.
13
- Buy and sell goods securely with smart contracts.
14
- </p>
15
- </div>
16
-
17
- <div>
18
- <h4 className="font-semibold text-black dark:text-white mb-4">Quick Links</h4>
19
- <ul className="space-y-2 text-sm text-gray-600 dark:text-gray-400">
20
- <li>
21
- <Link href="/marketplace" className="hover:text-black dark:hover:text-white transition-colors">
22
- Marketplace
23
- </Link>
24
- </li>
25
- <li>
26
- <Link href="/my-listings" className="hover:text-black dark:hover:text-white transition-colors">
27
- My Listings
28
- </Link>
29
- </li>
30
- <li>
31
- <Link href="/about" className="hover:text-black dark:hover:text-white transition-colors">
32
- About Us
33
- </Link>
34
- </li>
35
- <li>
36
- <Link href="/how-it-works" className="hover:text-black dark:hover:text-white transition-colors">
37
- How It Works
38
- </Link>
39
- </li>
40
- <li>
41
- <Link href="/help" className="hover:text-black dark:hover:text-white transition-colors">
42
- Help & FAQ
43
- </Link>
44
- </li>
45
- </ul>
46
- </div>
47
-
48
- <div>
49
- <h4 className="font-semibold text-black dark:text-white mb-4">Resources</h4>
50
- <ul className="space-y-2 text-sm text-gray-600 dark:text-gray-400">
51
- <li>
52
- <a
53
- href="https://www.stacks.co/"
54
- target="_blank"
55
- rel="noopener noreferrer"
56
- className="hover:text-black dark:hover:text-white transition-colors inline-flex items-center gap-1"
57
- >
58
- Stacks Blockchain
59
- <ExternalLink className="h-3 w-3" />
60
- </a>
61
- </li>
62
- <li>
63
- <a
64
- href="https://explorer.hiro.so/?chain=testnet"
65
- target="_blank"
66
- rel="noopener noreferrer"
67
- className="hover:text-black dark:hover:text-white transition-colors inline-flex items-center gap-1"
68
- >
69
- Testnet Explorer
70
- <ExternalLink className="h-3 w-3" />
71
- </a>
72
- </li>
73
- <li>
74
- <a
75
- href="https://github.com"
76
- target="_blank"
77
- rel="noopener noreferrer"
78
- className="hover:text-black dark:hover:text-white transition-colors inline-flex items-center gap-1"
79
- >
80
- <Github className="h-3 w-3" />
81
- GitHub
82
- </a>
83
- </li>
84
- </ul>
85
- </div>
86
- </div>
87
-
88
- <div className="border-t border-gray-200 dark:border-gray-800 mt-8 pt-8 text-center text-sm text-gray-600 dark:text-gray-400">
89
- <p>&copy; 2025 Strade. Built on Stacks blockchain. All rights reserved.</p>
90
- <p className="mt-2 text-xs text-gray-500 dark:text-gray-500">
91
- Testnet version - For demonstration purposes only
92
- </p>
93
- </div>
94
- </div>
95
- </footer>
96
- );
97
- }
98
- // grid-cols-1 md:grid-cols-4
99
- // text-center md:text-left
100
- // py-8