@trustless-work/blocks 1.0.6 → 1.0.7
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.
- package/bin/index.js +1930 -1921
- package/package.json +1 -1
- package/templates/deps.json +1 -1
- package/templates/escrows/details/Actions.tsx +1 -2
- package/templates/escrows/details/Entities.tsx +23 -2
- package/templates/escrows/details/GeneralInformation.tsx +1 -13
- package/templates/escrows/details/MilestoneCard.tsx +1 -1
- package/templates/escrows/details/MilestoneDetailDialog.tsx +38 -19
- package/templates/escrows/details/SuccessReleaseDialog.tsx +84 -28
- package/templates/escrows/details/useDetailsEscrow.ts +15 -2
- package/templates/escrows/multi-release/initialize-escrow/dialog/InitializeEscrow.tsx +76 -101
- package/templates/escrows/multi-release/initialize-escrow/form/InitializeEscrow.tsx +78 -102
- package/templates/escrows/multi-release/initialize-escrow/shared/schema.ts +8 -18
- package/templates/escrows/multi-release/initialize-escrow/shared/useInitializeEscrow.ts +21 -12
- package/templates/escrows/multi-release/release-milestone/button/ReleaseMilestone.tsx +5 -1
- package/templates/escrows/multi-release/update-escrow/dialog/UpdateEscrow.tsx +112 -101
- package/templates/escrows/multi-release/update-escrow/form/UpdateEscrow.tsx +103 -101
- package/templates/escrows/multi-release/update-escrow/shared/schema.ts +8 -16
- package/templates/escrows/multi-release/update-escrow/shared/useUpdateEscrow.ts +33 -14
- package/templates/escrows/multi-release/withdraw-remaining-funds/button/WithdrawRemainingFunds.tsx +0 -1
- package/templates/escrows/multi-release/withdraw-remaining-funds/shared/useWithdrawRemainingFunds.ts +0 -1
- package/templates/escrows/single-release/initialize-escrow/dialog/InitializeEscrow.tsx +2 -25
- package/templates/escrows/single-release/initialize-escrow/form/InitializeEscrow.tsx +3 -26
- package/templates/escrows/single-release/initialize-escrow/shared/schema.ts +0 -10
- package/templates/escrows/single-release/initialize-escrow/shared/useInitializeEscrow.ts +0 -4
- package/templates/escrows/single-release/release-escrow/button/ReleaseEscrow.tsx +5 -1
- package/templates/escrows/single-release/update-escrow/dialog/UpdateEscrow.tsx +41 -27
- package/templates/escrows/single-release/update-escrow/form/UpdateEscrow.tsx +38 -3
- package/templates/escrows/single-release/update-escrow/shared/useUpdateEscrow.ts +28 -14
- package/templates/providers/EscrowAmountProvider.tsx +8 -0
- package/templates/tanstack/useEscrowsMutations.ts +1 -6
- package/templates/wallet-kit/WalletButtons.tsx +2 -2
- package/templates/wallet-kit/WalletProvider.tsx +0 -1
|
@@ -22,6 +22,7 @@ import { useInitializeEscrow } from "./useInitializeEscrow";
|
|
|
22
22
|
import { Trash2, DollarSign, Percent, Loader2 } from "lucide-react";
|
|
23
23
|
import Link from "next/link";
|
|
24
24
|
import { trustlineOptions } from "@/components/tw-blocks/wallet-kit/trustlines";
|
|
25
|
+
import { Separator } from "__UI_BASE__/separator";
|
|
25
26
|
|
|
26
27
|
export const InitializeEscrowForm = () => {
|
|
27
28
|
const {
|
|
@@ -86,7 +87,7 @@ export const InitializeEscrowForm = () => {
|
|
|
86
87
|
return (
|
|
87
88
|
<Form {...form}>
|
|
88
89
|
<form onSubmit={handleSubmit} className="flex flex-col space-y-6">
|
|
89
|
-
<Card className="flex flex-col sm:flex-row justify-between items-start sm:items-center gap-4 p-4">
|
|
90
|
+
<Card className="flex w-full max-w-3xl flex-col sm:flex-row justify-between items-start sm:items-center gap-4 p-4">
|
|
90
91
|
<Link
|
|
91
92
|
className="flex-1"
|
|
92
93
|
href="https://docs.trustlesswork.com/trustless-work/technology-overview/escrow-types"
|
|
@@ -111,7 +112,7 @@ export const InitializeEscrowForm = () => {
|
|
|
111
112
|
</Button>
|
|
112
113
|
)}
|
|
113
114
|
</Card>
|
|
114
|
-
<div className="grid grid-cols-1 lg:grid-cols-
|
|
115
|
+
<div className="grid grid-cols-1 lg:grid-cols-2 gap-4">
|
|
115
116
|
<FormField
|
|
116
117
|
control={form.control}
|
|
117
118
|
name="title"
|
|
@@ -155,7 +156,9 @@ export const InitializeEscrowForm = () => {
|
|
|
155
156
|
</FormItem>
|
|
156
157
|
)}
|
|
157
158
|
/>
|
|
159
|
+
</div>
|
|
158
160
|
|
|
161
|
+
<div className="grid grid-cols-1 lg:grid-cols-2 gap-4">
|
|
159
162
|
<FormField
|
|
160
163
|
control={form.control}
|
|
161
164
|
name="trustline.address"
|
|
@@ -192,6 +195,34 @@ export const InitializeEscrowForm = () => {
|
|
|
192
195
|
</FormItem>
|
|
193
196
|
)}
|
|
194
197
|
/>
|
|
198
|
+
|
|
199
|
+
<FormField
|
|
200
|
+
control={form.control}
|
|
201
|
+
name="platformFee"
|
|
202
|
+
render={() => (
|
|
203
|
+
<FormItem>
|
|
204
|
+
<FormLabel className="flex items-center">
|
|
205
|
+
Platform Fee
|
|
206
|
+
<span className="text-destructive ml-1">*</span>
|
|
207
|
+
</FormLabel>
|
|
208
|
+
<FormControl>
|
|
209
|
+
<div className="relative">
|
|
210
|
+
<Percent
|
|
211
|
+
className="absolute left-3 top-1/2 -translate-y-1/2 text-gray-500"
|
|
212
|
+
size={18}
|
|
213
|
+
/>
|
|
214
|
+
<Input
|
|
215
|
+
placeholder="Enter platform fee"
|
|
216
|
+
className="pl-10"
|
|
217
|
+
value={form.watch("platformFee")?.toString() || ""}
|
|
218
|
+
onChange={handlePlatformFeeChange}
|
|
219
|
+
/>
|
|
220
|
+
</div>
|
|
221
|
+
</FormControl>
|
|
222
|
+
<FormMessage />
|
|
223
|
+
</FormItem>
|
|
224
|
+
)}
|
|
225
|
+
/>
|
|
195
226
|
</div>
|
|
196
227
|
|
|
197
228
|
<div className="grid grid-cols-1 lg:grid-cols-2 gap-4">
|
|
@@ -301,7 +332,7 @@ export const InitializeEscrowForm = () => {
|
|
|
301
332
|
/>
|
|
302
333
|
</div>
|
|
303
334
|
|
|
304
|
-
<div className="grid grid-cols-1
|
|
335
|
+
<div className="grid grid-cols-1 gap-4">
|
|
305
336
|
<FormField
|
|
306
337
|
control={form.control}
|
|
307
338
|
name="roles.platformAddress"
|
|
@@ -309,7 +340,7 @@ export const InitializeEscrowForm = () => {
|
|
|
309
340
|
<FormItem>
|
|
310
341
|
<FormLabel className="flex items-center justify-between">
|
|
311
342
|
<span className="flex items-center">
|
|
312
|
-
Platform
|
|
343
|
+
Platform
|
|
313
344
|
<span className="text-destructive ml-1">*</span>
|
|
314
345
|
</span>
|
|
315
346
|
</FormLabel>
|
|
@@ -327,82 +358,6 @@ export const InitializeEscrowForm = () => {
|
|
|
327
358
|
</FormItem>
|
|
328
359
|
)}
|
|
329
360
|
/>
|
|
330
|
-
<FormField
|
|
331
|
-
control={form.control}
|
|
332
|
-
name="roles.receiver"
|
|
333
|
-
render={({ field }) => (
|
|
334
|
-
<FormItem>
|
|
335
|
-
<FormLabel className="flex items-center justify-between">
|
|
336
|
-
<span className="flex items-center">
|
|
337
|
-
Receiver<span className="text-destructive ml-1">*</span>
|
|
338
|
-
</span>
|
|
339
|
-
</FormLabel>
|
|
340
|
-
|
|
341
|
-
<FormControl>
|
|
342
|
-
<Input
|
|
343
|
-
placeholder="Enter receiver address"
|
|
344
|
-
{...field}
|
|
345
|
-
onChange={(e) => {
|
|
346
|
-
field.onChange(e);
|
|
347
|
-
}}
|
|
348
|
-
/>
|
|
349
|
-
</FormControl>
|
|
350
|
-
<FormMessage />
|
|
351
|
-
</FormItem>
|
|
352
|
-
)}
|
|
353
|
-
/>
|
|
354
|
-
</div>
|
|
355
|
-
|
|
356
|
-
<div className="grid grid-cols-1 lg:grid-cols-2 gap-4">
|
|
357
|
-
<FormField
|
|
358
|
-
control={form.control}
|
|
359
|
-
name="platformFee"
|
|
360
|
-
render={() => (
|
|
361
|
-
<FormItem>
|
|
362
|
-
<FormLabel className="flex items-center">
|
|
363
|
-
Platform Fee<span className="text-destructive ml-1">*</span>
|
|
364
|
-
</FormLabel>
|
|
365
|
-
<FormControl>
|
|
366
|
-
<div className="relative">
|
|
367
|
-
<Percent
|
|
368
|
-
className="absolute left-3 top-1/2 -translate-y-1/2 text-gray-500"
|
|
369
|
-
size={18}
|
|
370
|
-
/>
|
|
371
|
-
<Input
|
|
372
|
-
placeholder="Enter platform fee"
|
|
373
|
-
className="pl-10"
|
|
374
|
-
value={form.watch("platformFee")?.toString() || ""}
|
|
375
|
-
onChange={handlePlatformFeeChange}
|
|
376
|
-
/>
|
|
377
|
-
</div>
|
|
378
|
-
</FormControl>
|
|
379
|
-
<FormMessage />
|
|
380
|
-
</FormItem>
|
|
381
|
-
)}
|
|
382
|
-
/>
|
|
383
|
-
|
|
384
|
-
<FormField
|
|
385
|
-
control={form.control}
|
|
386
|
-
name="receiverMemo"
|
|
387
|
-
render={({ field }) => (
|
|
388
|
-
<FormItem>
|
|
389
|
-
<FormLabel className="flex items-center">
|
|
390
|
-
Receiver Memo (opcional)
|
|
391
|
-
</FormLabel>
|
|
392
|
-
<FormControl>
|
|
393
|
-
<Input
|
|
394
|
-
type="text"
|
|
395
|
-
placeholder="Enter the escrow receiver Memo"
|
|
396
|
-
{...field}
|
|
397
|
-
onChange={(e) => {
|
|
398
|
-
field.onChange(e);
|
|
399
|
-
}}
|
|
400
|
-
/>
|
|
401
|
-
</FormControl>
|
|
402
|
-
<FormMessage />
|
|
403
|
-
</FormItem>
|
|
404
|
-
)}
|
|
405
|
-
/>
|
|
406
361
|
</div>
|
|
407
362
|
|
|
408
363
|
<FormField
|
|
@@ -432,20 +387,33 @@ export const InitializeEscrowForm = () => {
|
|
|
432
387
|
Milestones<span className="text-destructive ml-1">*</span>
|
|
433
388
|
</FormLabel>
|
|
434
389
|
{milestones.map((milestone, index) => (
|
|
435
|
-
<div key={index} className="space-y-4">
|
|
436
|
-
<div className="
|
|
437
|
-
<
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
390
|
+
<div key={index} className="space-y-4 max-w-3xl">
|
|
391
|
+
<div className="grid grid-cols-1 md:grid-cols-12 gap-4 items-center">
|
|
392
|
+
<div className="md:col-span-4">
|
|
393
|
+
<Input
|
|
394
|
+
placeholder="Enter receiver address"
|
|
395
|
+
value={milestone.receiver}
|
|
396
|
+
onChange={(e) => {
|
|
397
|
+
const updatedMilestones = [...milestones];
|
|
398
|
+
updatedMilestones[index].receiver = e.target.value;
|
|
399
|
+
form.setValue("milestones", updatedMilestones);
|
|
400
|
+
}}
|
|
401
|
+
/>
|
|
402
|
+
</div>
|
|
403
|
+
|
|
404
|
+
<div className="md:col-span-4">
|
|
405
|
+
<Input
|
|
406
|
+
placeholder="Milestone description"
|
|
407
|
+
value={milestone.description}
|
|
408
|
+
onChange={(e) => {
|
|
409
|
+
const updatedMilestones = [...milestones];
|
|
410
|
+
updatedMilestones[index].description = e.target.value;
|
|
411
|
+
form.setValue("milestones", updatedMilestones);
|
|
412
|
+
}}
|
|
413
|
+
/>
|
|
414
|
+
</div>
|
|
447
415
|
|
|
448
|
-
<div className="
|
|
416
|
+
<div className="md:col-span-3 relative">
|
|
449
417
|
<DollarSign
|
|
450
418
|
className="absolute left-3 top-1/2 -translate-y-1/2 text-gray-500"
|
|
451
419
|
size={18}
|
|
@@ -458,21 +426,29 @@ export const InitializeEscrowForm = () => {
|
|
|
458
426
|
/>
|
|
459
427
|
</div>
|
|
460
428
|
|
|
461
|
-
<
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
429
|
+
<div className="md:col-span-1 flex justify-end">
|
|
430
|
+
<Button
|
|
431
|
+
onClick={() => handleRemoveMilestone(index)}
|
|
432
|
+
className="p-2 bg-transparent text-red-500 hover:text-red-600"
|
|
433
|
+
disabled={milestones.length === 1}
|
|
434
|
+
type="button"
|
|
435
|
+
>
|
|
436
|
+
<Trash2 className="h-5 w-5" />
|
|
437
|
+
</Button>
|
|
438
|
+
</div>
|
|
469
439
|
</div>
|
|
470
440
|
|
|
441
|
+
{/* Separator */}
|
|
442
|
+
{index < milestones.length - 1 && (
|
|
443
|
+
<Separator className="w-full" />
|
|
444
|
+
)}
|
|
445
|
+
|
|
446
|
+
{/* Add button */}
|
|
471
447
|
{index === milestones.length - 1 && (
|
|
472
448
|
<div className="flex justify-end mt-4">
|
|
473
449
|
<Button
|
|
474
450
|
disabled={isAnyMilestoneEmpty}
|
|
475
|
-
className="w-full md:w-
|
|
451
|
+
className="w-full md:w-fit md:min-w-40 cursor-pointer"
|
|
476
452
|
variant="outline"
|
|
477
453
|
onClick={handleAddMilestone}
|
|
478
454
|
type="button"
|
|
@@ -50,14 +50,6 @@ export const useInitializeEscrowSchema = () => {
|
|
|
50
50
|
.refine((value) => isValidWallet(value), {
|
|
51
51
|
message: "Dispute resolver must be a valid wallet.",
|
|
52
52
|
}),
|
|
53
|
-
receiver: z
|
|
54
|
-
.string()
|
|
55
|
-
.min(1, {
|
|
56
|
-
message: "Receiver address is required.",
|
|
57
|
-
})
|
|
58
|
-
.refine((value) => isValidWallet(value), {
|
|
59
|
-
message: "Receiver address must be a valid wallet.",
|
|
60
|
-
}),
|
|
61
53
|
}),
|
|
62
54
|
engagementId: z.string().min(1, {
|
|
63
55
|
message: "Engagement is required.",
|
|
@@ -104,16 +96,6 @@ export const useInitializeEscrowSchema = () => {
|
|
|
104
96
|
message: "Platform fee can have a maximum of 2 decimal places.",
|
|
105
97
|
}
|
|
106
98
|
),
|
|
107
|
-
receiverMemo: z
|
|
108
|
-
.string()
|
|
109
|
-
.optional()
|
|
110
|
-
.refine((val) => !val || val.length >= 1, {
|
|
111
|
-
message: "Receiver Memo must be at least 1.",
|
|
112
|
-
})
|
|
113
|
-
.refine((val) => !val || /^[1-9][0-9]*$/.test(val), {
|
|
114
|
-
message:
|
|
115
|
-
"Receiver Memo must be a whole number greater than 0 (no decimals).",
|
|
116
|
-
}),
|
|
117
99
|
});
|
|
118
100
|
};
|
|
119
101
|
|
|
@@ -124,6 +106,14 @@ export const useInitializeEscrowSchema = () => {
|
|
|
124
106
|
milestones: z
|
|
125
107
|
.array(
|
|
126
108
|
z.object({
|
|
109
|
+
receiver: z
|
|
110
|
+
.string()
|
|
111
|
+
.min(1, {
|
|
112
|
+
message: "Receiver address is required.",
|
|
113
|
+
})
|
|
114
|
+
.refine((value) => isValidWallet(value), {
|
|
115
|
+
message: "Receiver address must be a valid wallet.",
|
|
116
|
+
}),
|
|
127
117
|
description: z.string().min(1, {
|
|
128
118
|
message: "Milestone description is required.",
|
|
129
119
|
}),
|
|
@@ -34,7 +34,6 @@ export function useInitializeEscrow() {
|
|
|
34
34
|
title: "",
|
|
35
35
|
description: "",
|
|
36
36
|
platformFee: undefined,
|
|
37
|
-
receiverMemo: "",
|
|
38
37
|
trustline: {
|
|
39
38
|
address: "",
|
|
40
39
|
},
|
|
@@ -42,25 +41,27 @@ export function useInitializeEscrow() {
|
|
|
42
41
|
approver: "",
|
|
43
42
|
serviceProvider: "",
|
|
44
43
|
platformAddress: "",
|
|
45
|
-
receiver: "",
|
|
46
44
|
releaseSigner: "",
|
|
47
45
|
disputeResolver: "",
|
|
48
46
|
},
|
|
49
|
-
milestones: [{ description: "", amount: "" }],
|
|
47
|
+
milestones: [{ receiver: "", description: "", amount: "" }],
|
|
50
48
|
},
|
|
51
49
|
mode: "onChange",
|
|
52
50
|
});
|
|
53
51
|
|
|
54
52
|
const milestones = form.watch("milestones");
|
|
55
53
|
const isAnyMilestoneEmpty = milestones.some(
|
|
56
|
-
(milestone) =>
|
|
54
|
+
(milestone) =>
|
|
55
|
+
milestone.description === "" ||
|
|
56
|
+
milestone.receiver === "" ||
|
|
57
|
+
milestone.amount === ""
|
|
57
58
|
);
|
|
58
59
|
|
|
59
60
|
const handleAddMilestone = () => {
|
|
60
61
|
const currentMilestones = form.getValues("milestones");
|
|
61
62
|
const updatedMilestones = [
|
|
62
63
|
...currentMilestones,
|
|
63
|
-
{ description: "", amount: "" },
|
|
64
|
+
{ receiver: "", description: "", amount: "" },
|
|
64
65
|
];
|
|
65
66
|
form.setValue("milestones", updatedMilestones);
|
|
66
67
|
};
|
|
@@ -79,7 +80,6 @@ export function useInitializeEscrow() {
|
|
|
79
80
|
title: "Design Landing Page",
|
|
80
81
|
description: "Landing for the new product of the company.",
|
|
81
82
|
platformFee: 5,
|
|
82
|
-
receiverMemo: "123",
|
|
83
83
|
trustline: {
|
|
84
84
|
address: usdc?.value || "",
|
|
85
85
|
},
|
|
@@ -87,14 +87,25 @@ export function useInitializeEscrow() {
|
|
|
87
87
|
approver: walletAddress || "",
|
|
88
88
|
serviceProvider: walletAddress || "",
|
|
89
89
|
platformAddress: walletAddress || "",
|
|
90
|
-
receiver: walletAddress || "",
|
|
91
90
|
releaseSigner: walletAddress || "",
|
|
92
91
|
disputeResolver: walletAddress || "",
|
|
93
92
|
},
|
|
94
93
|
milestones: [
|
|
95
|
-
{
|
|
96
|
-
|
|
97
|
-
|
|
94
|
+
{
|
|
95
|
+
receiver: walletAddress || "",
|
|
96
|
+
description: "Design the wireframe",
|
|
97
|
+
amount: 2,
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
receiver: walletAddress || "",
|
|
101
|
+
description: "Develop the wireframe",
|
|
102
|
+
amount: 2,
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
receiver: walletAddress || "",
|
|
106
|
+
description: "Deploy the wireframe",
|
|
107
|
+
amount: 2,
|
|
108
|
+
},
|
|
98
109
|
],
|
|
99
110
|
};
|
|
100
111
|
|
|
@@ -105,7 +116,6 @@ export function useInitializeEscrow() {
|
|
|
105
116
|
|
|
106
117
|
// Explicitly set the trustline field
|
|
107
118
|
form.setValue("trustline.address", usdc?.value || "");
|
|
108
|
-
form.setValue("trustline.decimals", 10000000);
|
|
109
119
|
};
|
|
110
120
|
|
|
111
121
|
const handleSubmit = form.handleSubmit(async (payload) => {
|
|
@@ -124,7 +134,6 @@ export function useInitializeEscrow() {
|
|
|
124
134
|
typeof payload.platformFee === "string"
|
|
125
135
|
? Number(payload.platformFee)
|
|
126
136
|
: payload.platformFee,
|
|
127
|
-
receiverMemo: Number(payload.receiverMemo) ?? 0,
|
|
128
137
|
signer: walletAddress || "",
|
|
129
138
|
milestones: payload.milestones.map((milestone) => ({
|
|
130
139
|
...milestone,
|
|
@@ -26,7 +26,8 @@ export const ReleaseMilestoneButton = ({
|
|
|
26
26
|
const { releaseFunds } = useEscrowsMutations();
|
|
27
27
|
const { selectedEscrow, updateEscrow } = useEscrowContext();
|
|
28
28
|
const dialogStates = useEscrowDialogs();
|
|
29
|
-
const { setAmounts } =
|
|
29
|
+
const { setAmounts, setLastReleasedMilestoneIndex } =
|
|
30
|
+
useEscrowAmountContext();
|
|
30
31
|
const { walletAddress } = useWalletContext();
|
|
31
32
|
const [isSubmitting, setIsSubmitting] = React.useState(false);
|
|
32
33
|
|
|
@@ -87,6 +88,9 @@ export const ReleaseMilestoneButton = ({
|
|
|
87
88
|
balance: (selectedEscrow?.balance || 0) - (selectedEscrow?.amount || 0),
|
|
88
89
|
});
|
|
89
90
|
|
|
91
|
+
// Remember which milestone was released for the success dialog
|
|
92
|
+
setLastReleasedMilestoneIndex(Number(milestoneIndex));
|
|
93
|
+
|
|
90
94
|
// Open success dialog
|
|
91
95
|
dialogStates.successRelease.setIsOpen(true);
|
|
92
96
|
} catch (error) {
|