@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
|
@@ -19,7 +19,7 @@ import {
|
|
|
19
19
|
} from "__UI_BASE__/select";
|
|
20
20
|
import { Textarea } from "__UI_BASE__/textarea";
|
|
21
21
|
import { useUpdateEscrow } from "./useUpdateEscrow";
|
|
22
|
-
import { Trash2, DollarSign, Percent, Loader2 } from "lucide-react";
|
|
22
|
+
import { Trash2, DollarSign, Percent, Loader2, Lock } from "lucide-react";
|
|
23
23
|
import Link from "next/link";
|
|
24
24
|
import { trustlineOptions } from "@/components/tw-blocks/wallet-kit/trustlines";
|
|
25
25
|
|
|
@@ -34,6 +34,8 @@ export const UpdateEscrowForm = () => {
|
|
|
34
34
|
handleRemoveMilestone,
|
|
35
35
|
handleAmountChange,
|
|
36
36
|
handlePlatformFeeChange,
|
|
37
|
+
isEscrowLocked,
|
|
38
|
+
initialMilestonesCount,
|
|
37
39
|
} = useUpdateEscrow();
|
|
38
40
|
|
|
39
41
|
return (
|
|
@@ -52,6 +54,22 @@ export const UpdateEscrowForm = () => {
|
|
|
52
54
|
<p className="text-muted-foreground mt-1">
|
|
53
55
|
Update escrow details and milestones
|
|
54
56
|
</p>
|
|
57
|
+
|
|
58
|
+
{isEscrowLocked && (
|
|
59
|
+
<div className="flex flex-col gap-2 text-sm bg-yellow-50 dark:bg-yellow-900/20 p-2 rounded-md border border-yellow-200 dark:border-yellow-800 mt-3 px-4">
|
|
60
|
+
<div className="flex items-center gap-2">
|
|
61
|
+
<Lock className="w-4 h-4 text-yellow-600 dark:text-yellow-500 font-medium" />
|
|
62
|
+
<span className="text-yellow-600 dark:text-yellow-500 font-medium">
|
|
63
|
+
Escrow is locked
|
|
64
|
+
</span>
|
|
65
|
+
</div>
|
|
66
|
+
|
|
67
|
+
<p className="text-muted-foreground font-medium">
|
|
68
|
+
When the escrow has balance, it cannot be updated in all
|
|
69
|
+
fields, just adding new milestones is allowed.
|
|
70
|
+
</p>
|
|
71
|
+
</div>
|
|
72
|
+
)}
|
|
55
73
|
</Link>
|
|
56
74
|
</Card>
|
|
57
75
|
<div className="grid grid-cols-1 lg:grid-cols-3 gap-4">
|
|
@@ -67,6 +85,7 @@ export const UpdateEscrowForm = () => {
|
|
|
67
85
|
<Input
|
|
68
86
|
placeholder="Escrow title"
|
|
69
87
|
{...field}
|
|
88
|
+
disabled={isEscrowLocked}
|
|
70
89
|
onChange={(e) => {
|
|
71
90
|
field.onChange(e);
|
|
72
91
|
}}
|
|
@@ -89,6 +108,7 @@ export const UpdateEscrowForm = () => {
|
|
|
89
108
|
<Input
|
|
90
109
|
placeholder="Enter identifier"
|
|
91
110
|
{...field}
|
|
111
|
+
disabled={isEscrowLocked}
|
|
92
112
|
onChange={(e) => {
|
|
93
113
|
field.onChange(e);
|
|
94
114
|
}}
|
|
@@ -110,6 +130,7 @@ export const UpdateEscrowForm = () => {
|
|
|
110
130
|
<FormControl>
|
|
111
131
|
<Select
|
|
112
132
|
value={field.value}
|
|
133
|
+
disabled={isEscrowLocked}
|
|
113
134
|
onValueChange={(e) => {
|
|
114
135
|
field.onChange(e);
|
|
115
136
|
}}
|
|
@@ -153,6 +174,7 @@ export const UpdateEscrowForm = () => {
|
|
|
153
174
|
<Input
|
|
154
175
|
placeholder="Enter approver address"
|
|
155
176
|
{...field}
|
|
177
|
+
disabled={isEscrowLocked}
|
|
156
178
|
onChange={(e) => {
|
|
157
179
|
field.onChange(e);
|
|
158
180
|
}}
|
|
@@ -179,6 +201,7 @@ export const UpdateEscrowForm = () => {
|
|
|
179
201
|
<Input
|
|
180
202
|
placeholder="Enter service provider address"
|
|
181
203
|
{...field}
|
|
204
|
+
disabled={isEscrowLocked}
|
|
182
205
|
onChange={(e) => {
|
|
183
206
|
field.onChange(e);
|
|
184
207
|
}}
|
|
@@ -207,6 +230,7 @@ export const UpdateEscrowForm = () => {
|
|
|
207
230
|
<Input
|
|
208
231
|
placeholder="Enter release signer address"
|
|
209
232
|
{...field}
|
|
233
|
+
disabled={isEscrowLocked}
|
|
210
234
|
onChange={(e) => {
|
|
211
235
|
field.onChange(e);
|
|
212
236
|
}}
|
|
@@ -233,6 +257,7 @@ export const UpdateEscrowForm = () => {
|
|
|
233
257
|
<Input
|
|
234
258
|
placeholder="Enter dispute resolver address"
|
|
235
259
|
{...field}
|
|
260
|
+
disabled={isEscrowLocked}
|
|
236
261
|
onChange={(e) => {
|
|
237
262
|
field.onChange(e);
|
|
238
263
|
}}
|
|
@@ -252,7 +277,7 @@ export const UpdateEscrowForm = () => {
|
|
|
252
277
|
<FormItem>
|
|
253
278
|
<FormLabel className="flex items-center justify-between">
|
|
254
279
|
<span className="flex items-center">
|
|
255
|
-
Platform
|
|
280
|
+
Platform
|
|
256
281
|
<span className="text-destructive ml-1">*</span>
|
|
257
282
|
</span>
|
|
258
283
|
</FormLabel>
|
|
@@ -285,6 +310,7 @@ export const UpdateEscrowForm = () => {
|
|
|
285
310
|
<Input
|
|
286
311
|
placeholder="Enter receiver address"
|
|
287
312
|
{...field}
|
|
313
|
+
disabled={isEscrowLocked}
|
|
288
314
|
onChange={(e) => {
|
|
289
315
|
field.onChange(e);
|
|
290
316
|
}}
|
|
@@ -316,6 +342,7 @@ export const UpdateEscrowForm = () => {
|
|
|
316
342
|
className="pl-10"
|
|
317
343
|
value={form.watch("platformFee")?.toString() || ""}
|
|
318
344
|
onChange={handlePlatformFeeChange}
|
|
345
|
+
disabled={isEscrowLocked}
|
|
319
346
|
/>
|
|
320
347
|
</div>
|
|
321
348
|
</FormControl>
|
|
@@ -343,6 +370,7 @@ export const UpdateEscrowForm = () => {
|
|
|
343
370
|
className="pl-10"
|
|
344
371
|
value={form.watch("amount")?.toString() || ""}
|
|
345
372
|
onChange={handleAmountChange}
|
|
373
|
+
disabled={isEscrowLocked}
|
|
346
374
|
/>
|
|
347
375
|
</div>
|
|
348
376
|
</FormControl>
|
|
@@ -364,6 +392,7 @@ export const UpdateEscrowForm = () => {
|
|
|
364
392
|
type="text"
|
|
365
393
|
placeholder="Enter the escrow receiver Memo"
|
|
366
394
|
{...field}
|
|
395
|
+
disabled={isEscrowLocked}
|
|
367
396
|
onChange={(e) => {
|
|
368
397
|
field.onChange(e);
|
|
369
398
|
}}
|
|
@@ -387,6 +416,7 @@ export const UpdateEscrowForm = () => {
|
|
|
387
416
|
<Textarea
|
|
388
417
|
placeholder="Escrow description"
|
|
389
418
|
{...field}
|
|
419
|
+
disabled={isEscrowLocked}
|
|
390
420
|
onChange={(e) => {
|
|
391
421
|
field.onChange(e);
|
|
392
422
|
}}
|
|
@@ -407,6 +437,7 @@ export const UpdateEscrowForm = () => {
|
|
|
407
437
|
<Input
|
|
408
438
|
placeholder="Milestone Description"
|
|
409
439
|
value={milestone.description}
|
|
440
|
+
disabled={isEscrowLocked && index < initialMilestonesCount}
|
|
410
441
|
className="w-full sm:flex-1"
|
|
411
442
|
onChange={(e) => {
|
|
412
443
|
const updatedMilestones = [...milestones];
|
|
@@ -418,7 +449,11 @@ export const UpdateEscrowForm = () => {
|
|
|
418
449
|
<Button
|
|
419
450
|
onClick={() => handleRemoveMilestone(index)}
|
|
420
451
|
className="p-2 bg-transparent text-destructive rounded-md border-none shadow-none hover:bg-transparent hover:shadow-none hover:text-destructive focus:ring-0 active:ring-0 self-start sm:self-center cursor-pointer"
|
|
421
|
-
|
|
452
|
+
type="button"
|
|
453
|
+
disabled={
|
|
454
|
+
(isEscrowLocked && index < initialMilestonesCount) ||
|
|
455
|
+
milestones.length === 1
|
|
456
|
+
}
|
|
422
457
|
>
|
|
423
458
|
<Trash2 className="h-5 w-5" />
|
|
424
459
|
</Button>
|
|
@@ -7,6 +7,9 @@ import {
|
|
|
7
7
|
UpdateSingleReleaseEscrowPayload,
|
|
8
8
|
UpdateSingleReleaseEscrowResponse,
|
|
9
9
|
SingleReleaseMilestone,
|
|
10
|
+
Roles,
|
|
11
|
+
GetEscrowsFromIndexerResponse,
|
|
12
|
+
MultiReleaseMilestone,
|
|
10
13
|
} from "@trustless-work/escrow/types";
|
|
11
14
|
import { toast } from "sonner";
|
|
12
15
|
import { useEscrowContext } from "@/components/tw-blocks/providers/EscrowProvider";
|
|
@@ -16,7 +19,6 @@ import {
|
|
|
16
19
|
ErrorResponse,
|
|
17
20
|
handleError,
|
|
18
21
|
} from "@/components/tw-blocks/handle-errors/handle";
|
|
19
|
-
import { GetEscrowsFromIndexerResponse } from "@trustless-work/escrow/types";
|
|
20
22
|
|
|
21
23
|
export function useUpdateEscrow() {
|
|
22
24
|
const [isSubmitting, setIsSubmitting] = React.useState(false);
|
|
@@ -28,6 +30,11 @@ export function useUpdateEscrow() {
|
|
|
28
30
|
const { selectedEscrow, setSelectedEscrow } = useEscrowContext();
|
|
29
31
|
const { updateEscrow } = useEscrowsMutations();
|
|
30
32
|
|
|
33
|
+
const isEscrowLocked = Number(selectedEscrow?.balance || 0) > 0;
|
|
34
|
+
const initialMilestonesCountRef = React.useRef<number>(
|
|
35
|
+
((selectedEscrow?.milestones as MultiReleaseMilestone[]) || []).length
|
|
36
|
+
);
|
|
37
|
+
|
|
31
38
|
const form = useForm<z.infer<typeof formSchema>>({
|
|
32
39
|
resolver: zodResolver(formSchema),
|
|
33
40
|
defaultValues: {
|
|
@@ -39,9 +46,6 @@ export function useUpdateEscrow() {
|
|
|
39
46
|
| string
|
|
40
47
|
| undefined,
|
|
41
48
|
amount: selectedEscrow?.amount as unknown as number | string | undefined,
|
|
42
|
-
receiverMemo: selectedEscrow?.receiverMemo
|
|
43
|
-
? String(selectedEscrow.receiverMemo)
|
|
44
|
-
: "",
|
|
45
49
|
trustline: {
|
|
46
50
|
address: selectedEscrow?.trustline?.address || "",
|
|
47
51
|
},
|
|
@@ -49,7 +53,9 @@ export function useUpdateEscrow() {
|
|
|
49
53
|
approver: selectedEscrow?.roles?.approver || "",
|
|
50
54
|
serviceProvider: selectedEscrow?.roles?.serviceProvider || "",
|
|
51
55
|
platformAddress: selectedEscrow?.roles?.platformAddress || "",
|
|
52
|
-
receiver:
|
|
56
|
+
receiver:
|
|
57
|
+
(selectedEscrow?.roles as Roles & { receiver?: string })?.receiver ||
|
|
58
|
+
"",
|
|
53
59
|
releaseSigner: selectedEscrow?.roles?.releaseSigner || "",
|
|
54
60
|
disputeResolver: selectedEscrow?.roles?.disputeResolver || "",
|
|
55
61
|
},
|
|
@@ -76,9 +82,6 @@ export function useUpdateEscrow() {
|
|
|
76
82
|
amount:
|
|
77
83
|
(selectedEscrow?.amount as unknown as number | string | undefined) ||
|
|
78
84
|
"",
|
|
79
|
-
receiverMemo: selectedEscrow?.receiverMemo
|
|
80
|
-
? String(selectedEscrow.receiverMemo)
|
|
81
|
-
: "",
|
|
82
85
|
trustline: {
|
|
83
86
|
address: selectedEscrow?.trustline?.address || "",
|
|
84
87
|
},
|
|
@@ -86,7 +89,9 @@ export function useUpdateEscrow() {
|
|
|
86
89
|
approver: selectedEscrow?.roles?.approver || "",
|
|
87
90
|
serviceProvider: selectedEscrow?.roles?.serviceProvider || "",
|
|
88
91
|
platformAddress: selectedEscrow?.roles?.platformAddress || "",
|
|
89
|
-
receiver:
|
|
92
|
+
receiver:
|
|
93
|
+
(selectedEscrow?.roles as Roles & { receiver?: string })?.receiver ||
|
|
94
|
+
"",
|
|
90
95
|
releaseSigner: selectedEscrow?.roles?.releaseSigner || "",
|
|
91
96
|
disputeResolver: selectedEscrow?.roles?.disputeResolver || "",
|
|
92
97
|
},
|
|
@@ -99,7 +104,13 @@ export function useUpdateEscrow() {
|
|
|
99
104
|
}, [selectedEscrow, form]);
|
|
100
105
|
|
|
101
106
|
const milestones = form.watch("milestones");
|
|
102
|
-
const isAnyMilestoneEmpty = milestones.some((m) =>
|
|
107
|
+
const isAnyMilestoneEmpty = milestones.some((m, index) => {
|
|
108
|
+
const shouldValidate =
|
|
109
|
+
!isEscrowLocked || index >= initialMilestonesCountRef.current;
|
|
110
|
+
if (!shouldValidate) return false;
|
|
111
|
+
|
|
112
|
+
return m.description === "";
|
|
113
|
+
});
|
|
103
114
|
|
|
104
115
|
const handleAddMilestone = () => {
|
|
105
116
|
const current = form.getValues("milestones");
|
|
@@ -164,14 +175,15 @@ export function useUpdateEscrow() {
|
|
|
164
175
|
typeof payload.amount === "string"
|
|
165
176
|
? Number(payload.amount)
|
|
166
177
|
: payload.amount,
|
|
167
|
-
receiverMemo: payload.receiverMemo
|
|
168
|
-
? Number(payload.receiverMemo)
|
|
169
|
-
: undefined,
|
|
170
178
|
trustline: {
|
|
171
179
|
address: payload.trustline.address,
|
|
172
180
|
},
|
|
173
181
|
roles: payload.roles,
|
|
174
|
-
milestones: payload.milestones,
|
|
182
|
+
milestones: payload.milestones.map((milestone, index) => ({
|
|
183
|
+
...milestone,
|
|
184
|
+
evidence: selectedEscrow?.milestones?.[index]?.evidence || "",
|
|
185
|
+
status: selectedEscrow?.milestones?.[index]?.status || "",
|
|
186
|
+
})),
|
|
175
187
|
},
|
|
176
188
|
};
|
|
177
189
|
|
|
@@ -221,5 +233,7 @@ export function useUpdateEscrow() {
|
|
|
221
233
|
handleRemoveMilestone,
|
|
222
234
|
handleAmountChange,
|
|
223
235
|
handlePlatformFeeChange,
|
|
236
|
+
isEscrowLocked,
|
|
237
|
+
initialMilestonesCount: initialMilestonesCountRef.current,
|
|
224
238
|
};
|
|
225
239
|
}
|
|
@@ -21,6 +21,8 @@ export type AmountEscrowStore = {
|
|
|
21
21
|
setReceiverResolve: (value: number) => void;
|
|
22
22
|
setApproverResolve: (value: number) => void;
|
|
23
23
|
setAmountMoonpay: (value: number) => void;
|
|
24
|
+
lastReleasedMilestoneIndex: number | null;
|
|
25
|
+
setLastReleasedMilestoneIndex: (index: number | null) => void;
|
|
24
26
|
};
|
|
25
27
|
|
|
26
28
|
const EscrowAmountContext = createContext<AmountEscrowStore | undefined>(
|
|
@@ -34,6 +36,9 @@ export const EscrowAmountProvider = ({ children }: { children: ReactNode }) => {
|
|
|
34
36
|
const [receiverResolve, setReceiverResolve] = useState(0);
|
|
35
37
|
const [approverResolve, setApproverResolve] = useState(0);
|
|
36
38
|
const [amountMoonpay, setAmountMoonpay] = useState(0);
|
|
39
|
+
const [lastReleasedMilestoneIndex, setLastReleasedMilestoneIndex] = useState<
|
|
40
|
+
number | null
|
|
41
|
+
>(null);
|
|
37
42
|
|
|
38
43
|
const setAmounts: AmountEscrowStore["setAmounts"] = useCallback(
|
|
39
44
|
(totalAmount, platformFee) => {
|
|
@@ -62,6 +67,8 @@ export const EscrowAmountProvider = ({ children }: { children: ReactNode }) => {
|
|
|
62
67
|
setReceiverResolve,
|
|
63
68
|
setApproverResolve,
|
|
64
69
|
setAmountMoonpay,
|
|
70
|
+
lastReleasedMilestoneIndex,
|
|
71
|
+
setLastReleasedMilestoneIndex,
|
|
65
72
|
}),
|
|
66
73
|
[
|
|
67
74
|
receiverAmount,
|
|
@@ -70,6 +77,7 @@ export const EscrowAmountProvider = ({ children }: { children: ReactNode }) => {
|
|
|
70
77
|
receiverResolve,
|
|
71
78
|
approverResolve,
|
|
72
79
|
amountMoonpay,
|
|
80
|
+
lastReleasedMilestoneIndex,
|
|
73
81
|
]
|
|
74
82
|
);
|
|
75
83
|
|
|
@@ -443,17 +443,12 @@ export const useEscrowsMutations = () => {
|
|
|
443
443
|
const withdrawRemainingFundsMutation = useMutation({
|
|
444
444
|
mutationFn: async ({
|
|
445
445
|
payload,
|
|
446
|
-
type,
|
|
447
446
|
address,
|
|
448
447
|
}: {
|
|
449
448
|
payload: WithdrawRemainingFundsPayload;
|
|
450
|
-
type: EscrowType;
|
|
451
449
|
address: string;
|
|
452
450
|
}) => {
|
|
453
|
-
const { unsignedTransaction } = await withdrawRemainingFunds(
|
|
454
|
-
payload,
|
|
455
|
-
type
|
|
456
|
-
);
|
|
451
|
+
const { unsignedTransaction } = await withdrawRemainingFunds(payload);
|
|
457
452
|
|
|
458
453
|
if (!unsignedTransaction) {
|
|
459
454
|
throw new Error(
|
|
@@ -29,7 +29,7 @@ export const WalletButton = () => {
|
|
|
29
29
|
setCopied(true);
|
|
30
30
|
setTimeout(() => setCopied(false), 1500);
|
|
31
31
|
} catch (_) {
|
|
32
|
-
|
|
32
|
+
console.error("Error copying address to clipboard", _);
|
|
33
33
|
}
|
|
34
34
|
};
|
|
35
35
|
|
|
@@ -39,7 +39,7 @@ export const WalletButton = () => {
|
|
|
39
39
|
<PopoverTrigger asChild>
|
|
40
40
|
<Button
|
|
41
41
|
variant="outline"
|
|
42
|
-
className="h-10 px-4 gap-2 font-medium bg-transparent"
|
|
42
|
+
className="h-10 px-4 gap-2 font-medium bg-transparent cursor-pointer"
|
|
43
43
|
>
|
|
44
44
|
<Wallet className="h-4 w-4" />
|
|
45
45
|
<span className="hidden sm:inline">{walletName}</span>
|