@trustless-work/blocks 1.0.0 → 1.0.2

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 (36) hide show
  1. package/bin/index.js +78 -1
  2. package/package.json +1 -1
  3. package/templates/deps.json +1 -1
  4. package/templates/escrows/details/Actions.tsx +21 -1
  5. package/templates/escrows/indicators/balance-progress/bar/BalanceProgress.tsx +55 -0
  6. package/templates/escrows/indicators/balance-progress/donut/BalanceProgress.tsx +99 -0
  7. package/templates/escrows/multi-release/initialize-escrow/dialog/InitializeEscrow.tsx +1 -0
  8. package/templates/escrows/multi-release/initialize-escrow/form/InitializeEscrow.tsx +1 -0
  9. package/templates/escrows/multi-release/initialize-escrow/shared/schema.ts +0 -1
  10. package/templates/escrows/multi-release/initialize-escrow/shared/useInitializeEscrow.ts +0 -2
  11. package/templates/escrows/multi-release/resolve-dispute/button/ResolveDispute.tsx +10 -20
  12. package/templates/escrows/multi-release/resolve-dispute/dialog/ResolveDispute.tsx +117 -60
  13. package/templates/escrows/multi-release/resolve-dispute/form/ResolveDispute.tsx +111 -55
  14. package/templates/escrows/multi-release/resolve-dispute/shared/schema.ts +68 -71
  15. package/templates/escrows/multi-release/resolve-dispute/shared/useResolveDispute.ts +107 -21
  16. package/templates/escrows/multi-release/update-escrow/shared/schema.ts +0 -1
  17. package/templates/escrows/multi-release/update-escrow/shared/useUpdateEscrow.ts +0 -4
  18. package/templates/escrows/multi-release/withdraw-remaining-funds/button/WithdrawRemainingFunds.tsx +85 -0
  19. package/templates/escrows/multi-release/withdraw-remaining-funds/dialog/WithdrawRemainingFunds.tsx +176 -0
  20. package/templates/escrows/multi-release/withdraw-remaining-funds/form/WithdrawRemainingFunds.tsx +153 -0
  21. package/templates/escrows/multi-release/withdraw-remaining-funds/shared/schema.ts +81 -0
  22. package/templates/escrows/multi-release/withdraw-remaining-funds/shared/useWithdrawRemainingFunds.ts +160 -0
  23. package/templates/escrows/single-multi-release/approve-milestone/button/ApproveMilestone.tsx +0 -1
  24. package/templates/escrows/single-multi-release/approve-milestone/shared/useApproveMilestone.ts +0 -1
  25. package/templates/escrows/single-release/initialize-escrow/shared/schema.ts +0 -1
  26. package/templates/escrows/single-release/initialize-escrow/shared/useInitializeEscrow.ts +0 -2
  27. package/templates/escrows/single-release/resolve-dispute/button/ResolveDispute.tsx +15 -31
  28. package/templates/escrows/single-release/resolve-dispute/dialog/ResolveDispute.tsx +116 -60
  29. package/templates/escrows/single-release/resolve-dispute/form/ResolveDispute.tsx +98 -43
  30. package/templates/escrows/single-release/resolve-dispute/shared/schema.ts +65 -68
  31. package/templates/escrows/single-release/resolve-dispute/shared/useResolveDispute.ts +100 -22
  32. package/templates/escrows/single-release/update-escrow/shared/schema.ts +0 -1
  33. package/templates/escrows/single-release/update-escrow/shared/useUpdateEscrow.ts +0 -4
  34. package/templates/tanstack/useEscrowsMutations.ts +53 -0
  35. package/templates/tanstack/useGetMultipleEscrowBalances.ts +41 -0
  36. package/templates/wallet-kit/trustlines.ts +0 -4
@@ -0,0 +1,176 @@
1
+ import * as React from "react";
2
+ import {
3
+ Form,
4
+ FormField,
5
+ FormItem,
6
+ FormLabel,
7
+ FormControl,
8
+ FormMessage,
9
+ } from "__UI_BASE__/form";
10
+ import { Input } from "__UI_BASE__/input";
11
+ import { Button } from "__UI_BASE__/button";
12
+ import {
13
+ Dialog,
14
+ DialogContent,
15
+ DialogHeader,
16
+ DialogTitle,
17
+ DialogTrigger,
18
+ } from "__UI_BASE__/dialog";
19
+ import { Loader2, Trash2 } from "lucide-react";
20
+ import { useWithdrawRemainingFunds } from "./useWithdrawRemainingFunds";
21
+ import { useEscrowContext } from "@/components/tw-blocks/providers/EscrowProvider";
22
+ import { formatCurrency } from "../../../../helpers/format.helper";
23
+
24
+ export const WithdrawRemainingFundsDialog = () => {
25
+ const {
26
+ form,
27
+ handleSubmit,
28
+ isSubmitting,
29
+ distributions,
30
+ handleAddDistribution,
31
+ handleRemoveDistribution,
32
+ handleDistributionAddressChange,
33
+ handleDistributionAmountChange,
34
+ isAnyDistributionEmpty,
35
+ allowedAmount,
36
+ distributedSum,
37
+ isExactMatch,
38
+ difference,
39
+ } = useWithdrawRemainingFunds();
40
+ const { selectedEscrow } = useEscrowContext();
41
+
42
+ return (
43
+ <Dialog>
44
+ <DialogTrigger asChild>
45
+ <Button type="button" className="cursor-pointer w-full">
46
+ Withdraw Remaining
47
+ </Button>
48
+ </DialogTrigger>
49
+ <DialogContent className="!w-full sm:!max-w-3xl max-h-[95vh] overflow-y-auto">
50
+ <DialogHeader>
51
+ <DialogTitle>Withdraw Remaining Funds</DialogTitle>
52
+ </DialogHeader>
53
+ <Form {...form}>
54
+ <form onSubmit={handleSubmit}>
55
+ <FormLabel className="flex items-center my-4">
56
+ Distributions<span className="text-destructive ml-1">*</span>
57
+ </FormLabel>
58
+
59
+ {distributions.map((d, idx) => (
60
+ <div
61
+ key={`dist-${idx}`}
62
+ className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-[1fr_minmax(140px,220px)_auto] gap-3 sm:gap-4 items-end mb-2"
63
+ >
64
+ <FormField
65
+ control={form.control}
66
+ name={`distributions.${idx}.address` as const}
67
+ render={() => (
68
+ <FormItem className="sm:col-span-2 lg:col-span-1">
69
+ <FormLabel>Address</FormLabel>
70
+ <FormControl>
71
+ <Input
72
+ type="text"
73
+ placeholder="Receiver address"
74
+ value={d.address}
75
+ onChange={(e) =>
76
+ handleDistributionAddressChange(idx, e.target.value)
77
+ }
78
+ />
79
+ </FormControl>
80
+ <FormMessage />
81
+ </FormItem>
82
+ )}
83
+ />
84
+
85
+ <FormField
86
+ control={form.control}
87
+ name={`distributions.${idx}.amount` as const}
88
+ render={() => (
89
+ <FormItem>
90
+ <FormLabel>Amount</FormLabel>
91
+ <FormControl>
92
+ <Input
93
+ type="text"
94
+ inputMode="decimal"
95
+ placeholder="0.00"
96
+ value={(d.amount as string) ?? ""}
97
+ onChange={(e) =>
98
+ handleDistributionAmountChange(idx, e)
99
+ }
100
+ />
101
+ </FormControl>
102
+ <FormMessage />
103
+ </FormItem>
104
+ )}
105
+ />
106
+
107
+ <Button
108
+ type="button"
109
+ onClick={() => handleRemoveDistribution(idx)}
110
+ className="justify-self-end self-end 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"
111
+ disabled={distributions.length <= 2}
112
+ >
113
+ <Trash2 className="h-5 w-5" />
114
+ </Button>
115
+ </div>
116
+ ))}
117
+
118
+ <div className="flex justify-between items-center mt-4">
119
+ <Button
120
+ type="button"
121
+ variant="outline"
122
+ onClick={handleAddDistribution}
123
+ disabled={isAnyDistributionEmpty}
124
+ className="cursor-pointer"
125
+ >
126
+ Add Item
127
+ </Button>
128
+
129
+ <div className="flex items-center gap-4">
130
+ <div className="text-xs text-muted-foreground">
131
+ <p>
132
+ <span className="font-bold">Total Amount: </span>
133
+ {distributedSum.toFixed(2)} / {allowedAmount.toFixed(2)}
134
+ </p>
135
+ {!isExactMatch && (
136
+ <p className="text-destructive">
137
+ <span className="font-bold">Difference: </span>
138
+ {difference.toFixed(2)}
139
+ </p>
140
+ )}
141
+ </div>
142
+
143
+ <p className="text-xs text-muted-foreground">
144
+ <span className="font-bold">Total Balance: </span>
145
+ {formatCurrency(
146
+ selectedEscrow?.balance || 0,
147
+ selectedEscrow?.trustline.name || ""
148
+ )}
149
+ </p>
150
+ </div>
151
+ </div>
152
+
153
+ <div className="mt-4 flex justify-start items-center">
154
+ <Button
155
+ type="submit"
156
+ disabled={
157
+ isSubmitting || isAnyDistributionEmpty || !isExactMatch
158
+ }
159
+ className="cursor-pointer"
160
+ >
161
+ {isSubmitting ? (
162
+ <div className="flex items-center">
163
+ <Loader2 className="h-5 w-5 animate-spin" />
164
+ <span className="ml-2">Withdrawing...</span>
165
+ </div>
166
+ ) : (
167
+ "Withdraw"
168
+ )}
169
+ </Button>
170
+ </div>
171
+ </form>
172
+ </Form>
173
+ </DialogContent>
174
+ </Dialog>
175
+ );
176
+ };
@@ -0,0 +1,153 @@
1
+ import * as React from "react";
2
+ import {
3
+ Form,
4
+ FormField,
5
+ FormItem,
6
+ FormLabel,
7
+ FormControl,
8
+ FormMessage,
9
+ } from "__UI_BASE__/form";
10
+ import { Input } from "__UI_BASE__/input";
11
+ import { Button } from "__UI_BASE__/button";
12
+ import { useWithdrawRemainingFunds } from "./useWithdrawRemainingFunds";
13
+ import { useEscrowContext } from "@/components/tw-blocks/providers/EscrowProvider";
14
+ import { Loader2, Trash2 } from "lucide-react";
15
+ import { formatCurrency } from "../../../../helpers/format.helper";
16
+
17
+ export const WithdrawRemainingFundsForm = () => {
18
+ const {
19
+ form,
20
+ handleSubmit,
21
+ isSubmitting,
22
+ distributions,
23
+ handleAddDistribution,
24
+ handleRemoveDistribution,
25
+ handleDistributionAddressChange,
26
+ handleDistributionAmountChange,
27
+ isAnyDistributionEmpty,
28
+ allowedAmount,
29
+ distributedSum,
30
+ isExactMatch,
31
+ difference,
32
+ } = useWithdrawRemainingFunds();
33
+ const { selectedEscrow } = useEscrowContext();
34
+
35
+ return (
36
+ <Form {...form}>
37
+ <form onSubmit={handleSubmit} className="flex flex-col space-y-6 w-full">
38
+ <FormLabel className="flex items-center my-4">
39
+ Distributions<span className="text-destructive ml-1">*</span>
40
+ </FormLabel>
41
+
42
+ {distributions.map((d, idx) => (
43
+ <div
44
+ key={`dist-${idx}`}
45
+ className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-[1fr_minmax(140px,220px)_auto] gap-3 sm:gap-4 items-end mb-2"
46
+ >
47
+ <FormField
48
+ control={form.control}
49
+ name={`distributions.${idx}.address` as const}
50
+ render={() => (
51
+ <FormItem className="sm:col-span-2 lg:col-span-1">
52
+ <FormLabel>Address</FormLabel>
53
+ <FormControl>
54
+ <Input
55
+ type="text"
56
+ placeholder="Receiver address"
57
+ value={d.address}
58
+ onChange={(e) =>
59
+ handleDistributionAddressChange(idx, e.target.value)
60
+ }
61
+ />
62
+ </FormControl>
63
+ <FormMessage />
64
+ </FormItem>
65
+ )}
66
+ />
67
+
68
+ <FormField
69
+ control={form.control}
70
+ name={`distributions.${idx}.amount` as const}
71
+ render={() => (
72
+ <FormItem>
73
+ <FormLabel>Amount</FormLabel>
74
+ <FormControl>
75
+ <Input
76
+ type="text"
77
+ inputMode="decimal"
78
+ placeholder="0.00"
79
+ value={(d.amount as string) ?? ""}
80
+ onChange={(e) => handleDistributionAmountChange(idx, e)}
81
+ />
82
+ </FormControl>
83
+ <FormMessage />
84
+ </FormItem>
85
+ )}
86
+ />
87
+
88
+ <Button
89
+ type="button"
90
+ onClick={() => handleRemoveDistribution(idx)}
91
+ className="justify-self-end self-end 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"
92
+ disabled={distributions.length <= 2}
93
+ >
94
+ <Trash2 className="h-5 w-5" />
95
+ </Button>
96
+ </div>
97
+ ))}
98
+
99
+ <div className="flex justify-between items-center">
100
+ <Button
101
+ type="button"
102
+ variant="outline"
103
+ onClick={handleAddDistribution}
104
+ disabled={isAnyDistributionEmpty}
105
+ className="cursor-pointer"
106
+ >
107
+ Add Item
108
+ </Button>
109
+
110
+ <div className="flex items-center gap-4">
111
+ <div className="text-xs text-muted-foreground">
112
+ <p>
113
+ <span className="font-bold">Total Amount: </span>
114
+ {distributedSum.toFixed(2)} / {allowedAmount.toFixed(2)}
115
+ </p>
116
+ {!isExactMatch && (
117
+ <p className="text-destructive">
118
+ <span className="font-bold">Difference: </span>
119
+ {difference.toFixed(2)}
120
+ </p>
121
+ )}
122
+ </div>
123
+
124
+ <p className="text-xs text-muted-foreground">
125
+ <span className="font-bold">Total Balance: </span>
126
+ {formatCurrency(
127
+ selectedEscrow?.balance || 0,
128
+ selectedEscrow?.trustline.name || ""
129
+ )}
130
+ </p>
131
+ </div>
132
+ </div>
133
+
134
+ <div className="mt-4">
135
+ <Button
136
+ type="submit"
137
+ disabled={isSubmitting || isAnyDistributionEmpty || !isExactMatch}
138
+ className="cursor-pointer"
139
+ >
140
+ {isSubmitting ? (
141
+ <div className="flex items-center">
142
+ <Loader2 className="h-5 w-5 animate-spin" />
143
+ <span className="ml-2">Withdrawing...</span>
144
+ </div>
145
+ ) : (
146
+ "Withdraw"
147
+ )}
148
+ </Button>
149
+ </div>
150
+ </form>
151
+ </Form>
152
+ );
153
+ };
@@ -0,0 +1,81 @@
1
+ import { z } from "zod";
2
+ import { isValidWallet } from "../../../../wallet-kit/validators";
3
+
4
+ export const getFormSchema = () => {
5
+ const amountSchema = z
6
+ .union([z.string(), z.number()])
7
+ .refine(
8
+ (val) => {
9
+ if (typeof val === "string") {
10
+ if (val === "" || val === "." || val.endsWith(".")) {
11
+ return true; // Allow partial input
12
+ }
13
+ const numVal = Number(val);
14
+ return !isNaN(numVal) && numVal >= 0;
15
+ }
16
+ return val >= 0;
17
+ },
18
+ { message: "Amount must be 0 or greater." }
19
+ )
20
+ .refine(
21
+ (val) => {
22
+ if (typeof val === "string") {
23
+ if (val === "" || val === "." || val.endsWith(".")) {
24
+ return true; // Allow partial input
25
+ }
26
+ const numVal = Number(val);
27
+ if (isNaN(numVal)) return false;
28
+ const decimalPlaces = (numVal.toString().split(".")[1] || "").length;
29
+ return decimalPlaces <= 2;
30
+ }
31
+ const decimalPlaces = (val.toString().split(".")[1] || "").length;
32
+ return decimalPlaces <= 2;
33
+ },
34
+ { message: "Amount can have a maximum of 2 decimal places." }
35
+ );
36
+
37
+ return z
38
+ .object({
39
+ distributions: z
40
+ .array(
41
+ z.object({
42
+ address: z
43
+ .string()
44
+ .min(1, { message: "Address is required." })
45
+ .refine((addr) => isValidWallet(addr), {
46
+ message: "Invalid Stellar address.",
47
+ }),
48
+ amount: amountSchema,
49
+ })
50
+ )
51
+ .min(2, { message: "At least two distributions are required." }),
52
+ })
53
+ .superRefine((data, ctx) => {
54
+ const seen = new Map<string, number>();
55
+ data.distributions.forEach((item, idx) => {
56
+ const key = (item.address || "").trim().toUpperCase();
57
+ if (!key) return;
58
+ if (seen.has(key)) {
59
+ const firstIdx = seen.get(key)!;
60
+ ctx.addIssue({
61
+ code: z.ZodIssueCode.custom,
62
+ path: ["distributions", idx, "address"],
63
+ message: "Duplicate address. Each recipient must be unique.",
64
+ });
65
+ ctx.addIssue({
66
+ code: z.ZodIssueCode.custom,
67
+ path: ["distributions", firstIdx, "address"],
68
+ message: "Duplicate address. Each recipient must be unique.",
69
+ });
70
+ } else {
71
+ seen.set(key, idx);
72
+ }
73
+ });
74
+ });
75
+ };
76
+
77
+ export const withdrawRemainingFundsSchema = getFormSchema();
78
+
79
+ export type WithdrawRemainingFundsValues = z.infer<
80
+ typeof withdrawRemainingFundsSchema
81
+ >;
@@ -0,0 +1,160 @@
1
+ import * as React from "react";
2
+ import { useForm } from "react-hook-form";
3
+ import { zodResolver } from "@hookform/resolvers/zod";
4
+ import {
5
+ withdrawRemainingFundsSchema,
6
+ type WithdrawRemainingFundsValues,
7
+ } from "./schema";
8
+ import { toast } from "sonner";
9
+ import { WithdrawRemainingFundsPayload } from "@trustless-work/escrow";
10
+ import { useEscrowContext } from "@/components/tw-blocks/providers/EscrowProvider";
11
+ import { useEscrowsMutations } from "@/components/tw-blocks/tanstack/useEscrowsMutations";
12
+ import {
13
+ ErrorResponse,
14
+ handleError,
15
+ } from "@/components/tw-blocks/handle-errors/handle";
16
+ import { useWalletContext } from "@/components/tw-blocks/wallet-kit/WalletProvider";
17
+
18
+ type DistributionInput = { address: string; amount: string | number };
19
+
20
+ export function useWithdrawRemainingFunds() {
21
+ const { withdrawRemainingFunds } = useEscrowsMutations();
22
+ const { selectedEscrow, updateEscrow } = useEscrowContext();
23
+ const { walletAddress } = useWalletContext();
24
+
25
+ const form = useForm<WithdrawRemainingFundsValues>({
26
+ resolver: zodResolver(withdrawRemainingFundsSchema),
27
+ defaultValues: {
28
+ distributions: [
29
+ { address: "", amount: "" },
30
+ { address: "", amount: "" },
31
+ ],
32
+ },
33
+ mode: "onChange",
34
+ });
35
+
36
+ const distributions = form.watch("distributions") as DistributionInput[];
37
+
38
+ const [isSubmitting, setIsSubmitting] = React.useState(false);
39
+
40
+ const allowedAmount = React.useMemo(() => {
41
+ return Number(selectedEscrow?.balance || 0);
42
+ }, [selectedEscrow]);
43
+
44
+ const distributedSum = React.useMemo(() => {
45
+ return (distributions || []).reduce((acc, d) => {
46
+ const n = Number(d?.amount ?? 0);
47
+ return acc + (isNaN(n) ? 0 : n);
48
+ }, 0);
49
+ }, [distributions]);
50
+
51
+ const isExactMatch = React.useMemo(() => {
52
+ return Number(allowedAmount) === Number(distributedSum);
53
+ }, [allowedAmount, distributedSum]);
54
+
55
+ const difference = React.useMemo(() => {
56
+ return Math.abs(Number(allowedAmount) - Number(distributedSum));
57
+ }, [allowedAmount, distributedSum]);
58
+
59
+ const handleDistributionAddressChange = (index: number, value: string) => {
60
+ const updated = [...distributions];
61
+ updated[index] = { ...updated[index], address: value };
62
+ form.setValue("distributions", updated);
63
+ };
64
+
65
+ const handleDistributionAmountChange = (
66
+ index: number,
67
+ e: React.ChangeEvent<HTMLInputElement>
68
+ ) => {
69
+ let rawValue = e.target.value;
70
+ rawValue = rawValue.replace(/[^0-9.]/g, "");
71
+ if (rawValue.split(".").length > 2) {
72
+ rawValue = rawValue.slice(0, -1);
73
+ }
74
+ if (rawValue.includes(".")) {
75
+ const parts = rawValue.split(".");
76
+ if (parts[1] && parts[1].length > 2) {
77
+ rawValue = parts[0] + "." + parts[1].slice(0, 2);
78
+ }
79
+ }
80
+ const updated = [...distributions];
81
+ updated[index] = { ...updated[index], amount: rawValue };
82
+ form.setValue("distributions", updated);
83
+ };
84
+
85
+ const handleAddDistribution = () => {
86
+ const updated = [...distributions, { address: "", amount: "" }];
87
+ form.setValue("distributions", updated);
88
+ };
89
+
90
+ const handleRemoveDistribution = (index: number) => {
91
+ if (distributions.length <= 2) return;
92
+ const updated = distributions.filter((_, i) => i !== index);
93
+ form.setValue("distributions", updated);
94
+ };
95
+
96
+ const isAnyDistributionEmpty = React.useMemo(() => {
97
+ if (!distributions.length) return true;
98
+ const last = distributions[distributions.length - 1];
99
+ return (last.address || "").trim() === "" || (last.amount ?? "") === "";
100
+ }, [distributions]);
101
+
102
+ const handleSubmit = form.handleSubmit(async (payload) => {
103
+ try {
104
+ setIsSubmitting(true);
105
+
106
+ if (!isExactMatch) {
107
+ toast.error("The total distributions must equal the remaining amount");
108
+ return;
109
+ }
110
+
111
+ const finalPayload: WithdrawRemainingFundsPayload = {
112
+ contractId: selectedEscrow?.contractId || "",
113
+ disputeResolver: walletAddress || "",
114
+ distributions: payload.distributions.map((d) => ({
115
+ address: d.address,
116
+ amount: Number(d.amount || 0),
117
+ })) as [{ address: string; amount: number }],
118
+ };
119
+
120
+ await withdrawRemainingFunds.mutateAsync({
121
+ payload: finalPayload,
122
+ type: "multi-release",
123
+ address: walletAddress || "",
124
+ });
125
+
126
+ toast.success("Withdraw successful");
127
+
128
+ const sumDistributed = payload.distributions.reduce((acc, d) => {
129
+ const n = Number(d.amount || 0);
130
+ return acc + (isNaN(n) ? 0 : n);
131
+ }, 0);
132
+
133
+ updateEscrow({
134
+ ...selectedEscrow,
135
+ balance: (selectedEscrow?.balance || 0) - sumDistributed || 0,
136
+ });
137
+ } catch (error) {
138
+ toast.error(handleError(error as ErrorResponse).message);
139
+ } finally {
140
+ setIsSubmitting(false);
141
+ form.reset();
142
+ }
143
+ });
144
+
145
+ return {
146
+ form,
147
+ handleSubmit,
148
+ isSubmitting,
149
+ distributions,
150
+ handleAddDistribution,
151
+ handleRemoveDistribution,
152
+ handleDistributionAddressChange,
153
+ handleDistributionAmountChange,
154
+ isAnyDistributionEmpty,
155
+ allowedAmount,
156
+ distributedSum,
157
+ isExactMatch,
158
+ difference,
159
+ };
160
+ }
@@ -40,7 +40,6 @@ export const ApproveMilestoneButton = ({
40
40
  contractId: selectedEscrow?.contractId || "",
41
41
  milestoneIndex: String(milestoneIndex),
42
42
  approver: walletAddress || "",
43
- newFlag: true,
44
43
  };
45
44
 
46
45
  /**
@@ -38,7 +38,6 @@ export function useApproveMilestone() {
38
38
  contractId: selectedEscrow?.contractId || "",
39
39
  milestoneIndex: payload.milestoneIndex,
40
40
  approver: walletAddress || "",
41
- newFlag: true,
42
41
  };
43
42
 
44
43
  await approveMilestone.mutateAsync({
@@ -8,7 +8,6 @@ export const useInitializeEscrowSchema = () => {
8
8
  address: z.string().min(1, {
9
9
  message: "Trustline address is required.",
10
10
  }),
11
- decimals: z.number().default(10000000),
12
11
  }),
13
12
  roles: z.object({
14
13
  approver: z
@@ -38,7 +38,6 @@ export function useInitializeEscrow() {
38
38
  receiverMemo: "",
39
39
  trustline: {
40
40
  address: "",
41
- decimals: 10000000,
42
41
  },
43
42
  roles: {
44
43
  approver: "",
@@ -82,7 +81,6 @@ export function useInitializeEscrow() {
82
81
  receiverMemo: "123",
83
82
  trustline: {
84
83
  address: usdc?.value || "",
85
- decimals: 10000000,
86
84
  },
87
85
  roles: {
88
86
  approver: walletAddress || "",