@trustless-work/blocks 1.1.4 → 1.1.6

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.
@@ -1,119 +1,119 @@
1
- "use client";
2
-
3
- import React from "react";
4
- import { useWalletContext } from "../../wallet-kit/WalletProvider";
5
- import { useEscrowsBySignerQuery } from "../../tanstack/useEscrowsBySignerQuery";
6
- import type { GetEscrowsFromIndexerResponse as Escrow } from "@trustless-work/escrow/types";
7
-
8
- type AmountsByDatePoint = { date: string; amount: number };
9
- type CreatedByDatePoint = { date: string; count: number };
10
- type DonutSlice = { type: "single" | "multi"; value: number; fill: string };
11
-
12
- function getCreatedDateKey(createdAt: Escrow["createdAt"]): string {
13
- // createdAt is a Firestore-like timestamp: { _seconds, _nanoseconds }
14
- const seconds = (createdAt as unknown as { _seconds?: number })?._seconds;
15
- const d = seconds ? new Date(seconds * 1000) : new Date();
16
- // YYYY-MM-DD
17
- return d.toISOString().slice(0, 10);
18
- }
19
-
20
- function getSingleReleaseAmount(escrow: Escrow): number {
21
- // Single release stores total in .amount
22
- const raw = (escrow as unknown as { amount?: number | string }).amount;
23
- const n = Number(raw ?? 0);
24
- return Number.isFinite(n) ? n : 0;
25
- }
26
-
27
- function getMultiReleaseAmount(escrow: Escrow): number {
28
- // Multi release accumulates across milestones
29
- const milestones = (
30
- escrow as unknown as {
31
- milestones?: Array<{ amount?: number | string }>;
32
- }
33
- ).milestones;
34
- if (!Array.isArray(milestones)) return 0;
35
- return milestones.reduce((acc: number, m) => {
36
- const n = Number(m?.amount ?? 0);
37
- return acc + (Number.isFinite(n) ? n : 0);
38
- }, 0);
39
- }
40
-
41
- function getEscrowAmount(escrow: Escrow): number {
42
- if (escrow.type === "single-release") return getSingleReleaseAmount(escrow);
43
- if (escrow.type === "multi-release") return getMultiReleaseAmount(escrow);
44
- return 0;
45
- }
46
-
47
- export function useDashboard() {
48
- const { walletAddress } = useWalletContext();
49
-
50
- const {
51
- data = [],
52
- isLoading,
53
- isFetching,
54
- isError,
55
- refetch,
56
- } = useEscrowsBySignerQuery({
57
- signer: walletAddress ?? "",
58
- enabled: !!walletAddress,
59
- });
60
-
61
- const totalEscrows = React.useMemo<number>(() => data.length, [data.length]);
62
-
63
- const totalAmount = React.useMemo<number>(() => {
64
- return data.reduce((acc: number, e) => acc + getEscrowAmount(e), 0);
65
- }, [data]);
66
-
67
- const totalBalance = React.useMemo<number>(() => {
68
- return data.reduce((acc: number, e) => acc + Number(e?.balance ?? 0), 0);
69
- }, [data]);
70
-
71
- const typeSlices = React.useMemo<DonutSlice[]>(() => {
72
- let single = 0;
73
- let multi = 0;
74
- for (const e of data) {
75
- if (e.type === "single-release") single += 1;
76
- else if (e.type === "multi-release") multi += 1;
77
- }
78
- return [
79
- { type: "single", value: single, fill: "var(--color-single)" },
80
- { type: "multi", value: multi, fill: "var(--color-multi)" },
81
- ];
82
- }, [data]);
83
-
84
- const amountsByDate = React.useMemo<AmountsByDatePoint[]>(() => {
85
- const map = new Map<string, number>();
86
- for (const e of data) {
87
- const key = getCreatedDateKey(e.createdAt);
88
- const current = map.get(key) ?? 0;
89
- map.set(key, current + getEscrowAmount(e));
90
- }
91
- return Array.from(map.entries())
92
- .map(([date, amount]) => ({ date, amount }))
93
- .sort((a, b) => (a.date < b.date ? -1 : a.date > b.date ? 1 : 0));
94
- }, [data]);
95
-
96
- const createdByDate = React.useMemo<CreatedByDatePoint[]>(() => {
97
- const map = new Map<string, number>();
98
- for (const e of data) {
99
- const key = getCreatedDateKey(e.createdAt);
100
- map.set(key, (map.get(key) ?? 0) + 1);
101
- }
102
- return Array.from(map.entries())
103
- .map(([date, count]) => ({ date, count }))
104
- .sort((a, b) => (a.date < b.date ? -1 : a.date > b.date ? 1 : 0));
105
- }, [data]);
106
-
107
- return {
108
- isLoading,
109
- isFetching,
110
- isError,
111
- refetch,
112
- totalEscrows,
113
- totalAmount,
114
- totalBalance,
115
- typeSlices,
116
- amountsByDate,
117
- createdByDate,
118
- } as const;
119
- }
1
+ "use client";
2
+
3
+ import React from "react";
4
+ import { useWalletContext } from "../../wallet-kit/WalletProvider";
5
+ import { useEscrowsBySignerQuery } from "../../tanstack/useEscrowsBySignerQuery";
6
+ import type { GetEscrowsFromIndexerResponse as Escrow } from "@trustless-work/escrow/types";
7
+
8
+ type AmountsByDatePoint = { date: string; amount: number };
9
+ type CreatedByDatePoint = { date: string; count: number };
10
+ type DonutSlice = { type: "single" | "multi"; value: number; fill: string };
11
+
12
+ function getCreatedDateKey(createdAt: Escrow["createdAt"]): string {
13
+ // createdAt is a Firestore-like timestamp: { _seconds, _nanoseconds }
14
+ const seconds = (createdAt as unknown as { _seconds?: number })?._seconds;
15
+ const d = seconds ? new Date(seconds * 1000) : new Date();
16
+ // YYYY-MM-DD
17
+ return d.toISOString().slice(0, 10);
18
+ }
19
+
20
+ function getSingleReleaseAmount(escrow: Escrow): number {
21
+ // Single release stores total in .amount
22
+ const raw = (escrow as unknown as { amount?: number | string }).amount;
23
+ const n = Number(raw ?? 0);
24
+ return Number.isFinite(n) ? n : 0;
25
+ }
26
+
27
+ function getMultiReleaseAmount(escrow: Escrow): number {
28
+ // Multi release accumulates across milestones
29
+ const milestones = (
30
+ escrow as unknown as {
31
+ milestones?: Array<{ amount?: number | string }>;
32
+ }
33
+ ).milestones;
34
+ if (!Array.isArray(milestones)) return 0;
35
+ return milestones.reduce((acc: number, m) => {
36
+ const n = Number(m?.amount ?? 0);
37
+ return acc + (Number.isFinite(n) ? n : 0);
38
+ }, 0);
39
+ }
40
+
41
+ function getEscrowAmount(escrow: Escrow): number {
42
+ if (escrow.type === "single-release") return getSingleReleaseAmount(escrow);
43
+ if (escrow.type === "multi-release") return getMultiReleaseAmount(escrow);
44
+ return 0;
45
+ }
46
+
47
+ export function useDashboard() {
48
+ const { walletAddress } = useWalletContext();
49
+
50
+ const {
51
+ data = [],
52
+ isLoading,
53
+ isFetching,
54
+ isError,
55
+ refetch,
56
+ } = useEscrowsBySignerQuery({
57
+ signer: walletAddress ?? "",
58
+ enabled: !!walletAddress,
59
+ });
60
+
61
+ const totalEscrows = React.useMemo<number>(() => data.length, [data.length]);
62
+
63
+ const totalAmount = React.useMemo<number>(() => {
64
+ return data.reduce((acc: number, e) => acc + getEscrowAmount(e), 0);
65
+ }, [data]);
66
+
67
+ const totalBalance = React.useMemo<number>(() => {
68
+ return data.reduce((acc: number, e) => acc + Number(e?.balance ?? 0), 0);
69
+ }, [data]);
70
+
71
+ const typeSlices = React.useMemo<DonutSlice[]>(() => {
72
+ let single = 0;
73
+ let multi = 0;
74
+ for (const e of data) {
75
+ if (e.type === "single-release") single += 1;
76
+ else if (e.type === "multi-release") multi += 1;
77
+ }
78
+ return [
79
+ { type: "single", value: single, fill: "var(--color-single)" },
80
+ { type: "multi", value: multi, fill: "var(--color-multi)" },
81
+ ];
82
+ }, [data]);
83
+
84
+ const amountsByDate = React.useMemo<AmountsByDatePoint[]>(() => {
85
+ const map = new Map<string, number>();
86
+ for (const e of data) {
87
+ const key = getCreatedDateKey(e.createdAt);
88
+ const current = map.get(key) ?? 0;
89
+ map.set(key, current + getEscrowAmount(e));
90
+ }
91
+ return Array.from(map.entries())
92
+ .map(([date, amount]) => ({ date, amount }))
93
+ .sort((a, b) => (a.date < b.date ? -1 : a.date > b.date ? 1 : 0));
94
+ }, [data]);
95
+
96
+ const createdByDate = React.useMemo<CreatedByDatePoint[]>(() => {
97
+ const map = new Map<string, number>();
98
+ for (const e of data) {
99
+ const key = getCreatedDateKey(e.createdAt);
100
+ map.set(key, (map.get(key) ?? 0) + 1);
101
+ }
102
+ return Array.from(map.entries())
103
+ .map(([date, count]) => ({ date, count }))
104
+ .sort((a, b) => (a.date < b.date ? -1 : a.date > b.date ? 1 : 0));
105
+ }, [data]);
106
+
107
+ return {
108
+ isLoading,
109
+ isFetching,
110
+ isError,
111
+ refetch,
112
+ totalEscrows,
113
+ totalAmount,
114
+ totalBalance,
115
+ typeSlices,
116
+ amountsByDate,
117
+ createdByDate,
118
+ } as const;
119
+ }
@@ -4,7 +4,7 @@
4
4
  "react-dom": "^18.2.0",
5
5
  "react-hook-form": "^7.53.0",
6
6
  "zod": "^3.23.8",
7
- "@trustless-work/escrow": "^3.0.3",
7
+ "@trustless-work/escrow": "^3.0.4",
8
8
  "@tanstack/react-query": "^5.75.0",
9
9
  "@tanstack/react-query-devtools": "^5.75.0",
10
10
  "tailwindcss": "^3.3.3",
@@ -1,166 +1,166 @@
1
- import {
2
- DollarSign,
3
- CheckCircle,
4
- CheckSquare,
5
- AlertTriangle,
6
- Edit,
7
- Scale,
8
- Unlock,
9
- Wallet,
10
- Settings,
11
- Briefcase,
12
- } from "lucide-react";
13
- import {
14
- GetEscrowsFromIndexerResponse as Escrow,
15
- Role,
16
- } from "@trustless-work/escrow/types";
17
- import { FundEscrowDialog } from "../../single-multi-release/fund-escrow/dialog/FundEscrow";
18
-
19
- interface ActionsProps {
20
- selectedEscrow: Escrow;
21
- userRolesInEscrow: string[];
22
- areAllMilestonesApproved: boolean;
23
- }
24
-
25
- export const roleActions: {
26
- role: Role;
27
- actions: string[];
28
- icon: React.ReactNode;
29
- color: string;
30
- }[] = [
31
- {
32
- role: "signer",
33
- actions: ["fundEscrow"],
34
- icon: <Wallet className="h-6 w-6 text-primary" />,
35
- color: "",
36
- },
37
- {
38
- role: "approver",
39
- actions: ["fundEscrow", "approveMilestone", "startDispute"],
40
- icon: <CheckCircle className="h-6 w-6 text-primary" />,
41
- color: "0",
42
- },
43
- {
44
- role: "serviceProvider",
45
- actions: ["fundEscrow", "completeMilestone", "startDispute"],
46
- icon: <Briefcase className="h-6 w-6 text-primary" />,
47
- color: "0",
48
- },
49
- {
50
- role: "disputeResolver",
51
- actions: ["fundEscrow", "resolveDispute"],
52
- icon: <Scale className="h-6 w-6 text-primary" />,
53
- color: "00",
54
- },
55
- {
56
- role: "releaseSigner",
57
- actions: ["fundEscrow", "releasePayment"],
58
- icon: <Unlock className="h-6 w-6 text-primary" />,
59
- color: "",
60
- },
61
- {
62
- role: "platformAddress",
63
- actions: ["fundEscrow", "editEscrow"],
64
- icon: <Settings className="h-6 w-6 text-primary" />,
65
- color: "0",
66
- },
67
- {
68
- role: "receiver",
69
- actions: ["fundEscrow"],
70
- icon: <DollarSign className="h-6 w-6 text-primary" />,
71
- color: "",
72
- },
73
- ];
74
-
75
- export const actionIcons: Record<string, React.ReactNode> = {
76
- fundEscrow: <DollarSign className="h-6 w-6 text-primary/60" />,
77
- approveMilestone: <CheckCircle className="h-6 w-6 text-primary/60" />,
78
- completeMilestone: <CheckSquare className="h-6 w-6 text-primary/60" />,
79
- startDispute: <AlertTriangle className="h-6 w-6 text-primary/60" />,
80
- resolveDispute: <Scale className="h-6 w-6 text-primary/60" />,
81
- releasePayment: <Unlock className="h-6 w-6 text-primary/60" />,
82
- editEscrow: <Edit className="h-6 w-6 text-primary/60" />,
83
- };
84
-
85
- export const Actions = ({
86
- selectedEscrow,
87
- userRolesInEscrow,
88
- areAllMilestonesApproved,
89
- }: ActionsProps) => {
90
- const shouldShowEditButton =
91
- userRolesInEscrow.includes("platformAddress") &&
92
- !selectedEscrow?.flags?.disputed &&
93
- !selectedEscrow?.flags?.resolved &&
94
- !selectedEscrow?.flags?.released;
95
-
96
- const shouldShowDisputeButton =
97
- selectedEscrow.type === "single-release" &&
98
- (userRolesInEscrow.includes("approver") ||
99
- userRolesInEscrow.includes("serviceProvider")) &&
100
- !selectedEscrow?.flags?.disputed &&
101
- !selectedEscrow?.flags?.resolved;
102
-
103
- const shouldShowResolveButton =
104
- selectedEscrow.type === "single-release" &&
105
- userRolesInEscrow.includes("disputeResolver") &&
106
- !selectedEscrow?.flags?.resolved &&
107
- selectedEscrow?.flags?.disputed;
108
-
109
- const shouldShowReleaseFundsButton =
110
- selectedEscrow.type === "single-release" &&
111
- areAllMilestonesApproved &&
112
- userRolesInEscrow.includes("releaseSigner") &&
113
- !selectedEscrow.flags?.released;
114
-
115
- const shouldShowWithdrawRemaining = (() => {
116
- if (selectedEscrow.type !== "multi-release") return false;
117
- if (!userRolesInEscrow.includes("disputeResolver")) return false;
118
- if ((selectedEscrow.balance ?? 0) === 0) return false;
119
- const milestones = (selectedEscrow.milestones || []) as Array<{
120
- flags?: { resolved?: boolean; released?: boolean; disputed?: boolean };
121
- }>;
122
- return (
123
- milestones.length > 0 &&
124
- milestones.every((m) => {
125
- const f = m.flags || {};
126
- return !!(f.resolved || f.released || f.disputed);
127
- })
128
- );
129
- })();
130
-
131
- const hasConditionalButtons =
132
- shouldShowEditButton ||
133
- shouldShowDisputeButton ||
134
- shouldShowResolveButton ||
135
- shouldShowReleaseFundsButton ||
136
- shouldShowWithdrawRemaining;
137
-
138
- return (
139
- <div className="flex items-start justify-start flex-col gap-2 w-full">
140
- {/* You can add the buttons here, using the buttons from the blocks. These actions are conditional based on the escrow flags and the user roles. */}
141
- {hasConditionalButtons && (
142
- <div className="flex flex-col gap-2 w-full">
143
- {/* UpdateEscrowDialog component should be rendered based on the escrow type. It means that if the selectedEscrow.type is "single-release", then the UpdateEscrowDialog (from the single-release block) component should be rendered. If the selectedEscrow.type is "multi-release", then the UpdateEscrowDialog (from the multi-release block) component should be rendered. */}
144
- {/* {shouldShowEditButton && <UpdateEscrowDialog />} */}
145
-
146
- {/* Works only with single-release escrows */}
147
- {/* Only appears if the escrow has balance */}
148
- {/* {shouldShowDisputeButton && <DisputeEscrowButton />} */}
149
-
150
- {/* Works only with single-release escrows */}
151
- {/* Only appears if the escrow is disputed */}
152
- {/* {shouldShowResolveButton && <ResolveDisputeDialog />} */}
153
-
154
- {/* Works only with single-release escrows */}
155
- {/* Only appears if all the milestones are approved */}
156
- {/* {shouldShowReleaseFundsButton && <ReleaseEscrowButton />} */}
157
-
158
- {/* Multi-release: Withdraw Remaining Funds */}
159
- {/* {shouldShowWithdrawRemaining && <WithdrawRemainingFundsDialog />} */}
160
- </div>
161
- )}
162
-
163
- <FundEscrowDialog />
164
- </div>
165
- );
166
- };
1
+ import {
2
+ DollarSign,
3
+ CheckCircle,
4
+ CheckSquare,
5
+ AlertTriangle,
6
+ Edit,
7
+ Scale,
8
+ Unlock,
9
+ Wallet,
10
+ Settings,
11
+ Briefcase,
12
+ } from "lucide-react";
13
+ import {
14
+ GetEscrowsFromIndexerResponse as Escrow,
15
+ Role,
16
+ } from "@trustless-work/escrow/types";
17
+ import { FundEscrowDialog } from "../../single-multi-release/fund-escrow/dialog/FundEscrow";
18
+
19
+ interface ActionsProps {
20
+ selectedEscrow: Escrow;
21
+ userRolesInEscrow: string[];
22
+ areAllMilestonesApproved: boolean;
23
+ }
24
+
25
+ export const roleActions: {
26
+ role: Role;
27
+ actions: string[];
28
+ icon: React.ReactNode;
29
+ color: string;
30
+ }[] = [
31
+ {
32
+ role: "signer",
33
+ actions: ["fundEscrow"],
34
+ icon: <Wallet className="h-6 w-6 text-primary" />,
35
+ color: "",
36
+ },
37
+ {
38
+ role: "approver",
39
+ actions: ["fundEscrow", "approveMilestone", "startDispute"],
40
+ icon: <CheckCircle className="h-6 w-6 text-primary" />,
41
+ color: "0",
42
+ },
43
+ {
44
+ role: "serviceProvider",
45
+ actions: ["fundEscrow", "completeMilestone", "startDispute"],
46
+ icon: <Briefcase className="h-6 w-6 text-primary" />,
47
+ color: "0",
48
+ },
49
+ {
50
+ role: "disputeResolver",
51
+ actions: ["fundEscrow", "resolveDispute"],
52
+ icon: <Scale className="h-6 w-6 text-primary" />,
53
+ color: "00",
54
+ },
55
+ {
56
+ role: "releaseSigner",
57
+ actions: ["fundEscrow", "releasePayment"],
58
+ icon: <Unlock className="h-6 w-6 text-primary" />,
59
+ color: "",
60
+ },
61
+ {
62
+ role: "platformAddress",
63
+ actions: ["fundEscrow", "editEscrow"],
64
+ icon: <Settings className="h-6 w-6 text-primary" />,
65
+ color: "0",
66
+ },
67
+ {
68
+ role: "receiver",
69
+ actions: ["fundEscrow"],
70
+ icon: <DollarSign className="h-6 w-6 text-primary" />,
71
+ color: "",
72
+ },
73
+ ];
74
+
75
+ export const actionIcons: Record<string, React.ReactNode> = {
76
+ fundEscrow: <DollarSign className="h-6 w-6 text-primary/60" />,
77
+ approveMilestone: <CheckCircle className="h-6 w-6 text-primary/60" />,
78
+ completeMilestone: <CheckSquare className="h-6 w-6 text-primary/60" />,
79
+ startDispute: <AlertTriangle className="h-6 w-6 text-primary/60" />,
80
+ resolveDispute: <Scale className="h-6 w-6 text-primary/60" />,
81
+ releasePayment: <Unlock className="h-6 w-6 text-primary/60" />,
82
+ editEscrow: <Edit className="h-6 w-6 text-primary/60" />,
83
+ };
84
+
85
+ export const Actions = ({
86
+ selectedEscrow,
87
+ userRolesInEscrow,
88
+ areAllMilestonesApproved,
89
+ }: ActionsProps) => {
90
+ const shouldShowEditButton =
91
+ userRolesInEscrow.includes("platformAddress") &&
92
+ !selectedEscrow?.flags?.disputed &&
93
+ !selectedEscrow?.flags?.resolved &&
94
+ !selectedEscrow?.flags?.released;
95
+
96
+ const shouldShowDisputeButton =
97
+ selectedEscrow.type === "single-release" &&
98
+ (userRolesInEscrow.includes("approver") ||
99
+ userRolesInEscrow.includes("serviceProvider")) &&
100
+ !selectedEscrow?.flags?.disputed &&
101
+ !selectedEscrow?.flags?.resolved;
102
+
103
+ const shouldShowResolveButton =
104
+ selectedEscrow.type === "single-release" &&
105
+ userRolesInEscrow.includes("disputeResolver") &&
106
+ !selectedEscrow?.flags?.resolved &&
107
+ selectedEscrow?.flags?.disputed;
108
+
109
+ const shouldShowReleaseFundsButton =
110
+ selectedEscrow.type === "single-release" &&
111
+ areAllMilestonesApproved &&
112
+ userRolesInEscrow.includes("releaseSigner") &&
113
+ !selectedEscrow.flags?.released;
114
+
115
+ const shouldShowWithdrawRemaining = (() => {
116
+ if (selectedEscrow.type !== "multi-release") return false;
117
+ if (!userRolesInEscrow.includes("disputeResolver")) return false;
118
+ if ((selectedEscrow.balance ?? 0) === 0) return false;
119
+ const milestones = (selectedEscrow.milestones || []) as Array<{
120
+ flags?: { resolved?: boolean; released?: boolean; disputed?: boolean };
121
+ }>;
122
+ return (
123
+ milestones.length > 0 &&
124
+ milestones.every((m) => {
125
+ const f = m.flags || {};
126
+ return !!(f.resolved || f.released || f.disputed);
127
+ })
128
+ );
129
+ })();
130
+
131
+ const hasConditionalButtons =
132
+ shouldShowEditButton ||
133
+ shouldShowDisputeButton ||
134
+ shouldShowResolveButton ||
135
+ shouldShowReleaseFundsButton ||
136
+ shouldShowWithdrawRemaining;
137
+
138
+ return (
139
+ <div className="flex items-start justify-start flex-col gap-2 w-full">
140
+ {/* You can add the buttons here, using the buttons from the blocks. These actions are conditional based on the escrow flags and the user roles. */}
141
+ {hasConditionalButtons && (
142
+ <div className="flex flex-col gap-2 w-full">
143
+ {/* UpdateEscrowDialog component should be rendered based on the escrow type. It means that if the selectedEscrow.type is "single-release", then the UpdateEscrowDialog (from the single-release block) component should be rendered. If the selectedEscrow.type is "multi-release", then the UpdateEscrowDialog (from the multi-release block) component should be rendered. */}
144
+ {/* {shouldShowEditButton && <UpdateEscrowDialog />} */}
145
+
146
+ {/* Works only with single-release escrows */}
147
+ {/* Only appears if the escrow has balance */}
148
+ {/* {shouldShowDisputeButton && <DisputeEscrowButton />} */}
149
+
150
+ {/* Works only with single-release escrows */}
151
+ {/* Only appears if the escrow is disputed */}
152
+ {/* {shouldShowResolveButton && <ResolveDisputeDialog />} */}
153
+
154
+ {/* Works only with single-release escrows */}
155
+ {/* Only appears if all the milestones are approved */}
156
+ {/* {shouldShowReleaseFundsButton && <ReleaseEscrowButton />} */}
157
+
158
+ {/* Multi-release: Withdraw Remaining Funds */}
159
+ {/* {shouldShowWithdrawRemaining && <WithdrawRemainingFundsDialog />} */}
160
+ </div>
161
+ )}
162
+
163
+ <FundEscrowDialog />
164
+ </div>
165
+ );
166
+ };
@@ -0,0 +1,64 @@
1
+ import * as React from "react";
2
+ import { Button } from "__UI_BASE__/button";
3
+ import { toast } from "sonner";
4
+ import {
5
+ ErrorResponse,
6
+ handleError,
7
+ } from "@/components/tw-blocks/handle-errors/handle";
8
+ import { Loader2 } from "lucide-react";
9
+ import { useGetEscrowFromIndexerByContractIds } from "@trustless-work/escrow/hooks";
10
+ import { useEscrowContext } from "@/components/tw-blocks/providers/EscrowProvider";
11
+ import { GetEscrowsFromIndexerResponse } from "@trustless-work/escrow/types";
12
+
13
+ type LoadEscrowButtonProps = {
14
+ contractId: string;
15
+ };
16
+
17
+ export const LoadEscrowButton = ({ contractId }: LoadEscrowButtonProps) => {
18
+ const [isSubmitting, setIsSubmitting] = React.useState(false);
19
+ const { getEscrowByContractIds } = useGetEscrowFromIndexerByContractIds();
20
+ const { setSelectedEscrow } = useEscrowContext();
21
+
22
+ async function handleClick() {
23
+ try {
24
+ setIsSubmitting(true);
25
+
26
+ const data = (await getEscrowByContractIds({
27
+ contractIds: [contractId],
28
+ validateOnChain: true,
29
+ })) as unknown as GetEscrowsFromIndexerResponse[];
30
+
31
+ const escrowData = data[0];
32
+
33
+ if (!escrowData) {
34
+ throw new Error("No escrow data received");
35
+ }
36
+
37
+ setSelectedEscrow(escrowData);
38
+
39
+ toast.success("Escrow data fetched successfully");
40
+ } catch (error) {
41
+ toast.error(handleError(error as ErrorResponse).message);
42
+ } finally {
43
+ setIsSubmitting(false);
44
+ }
45
+ }
46
+
47
+ return (
48
+ <Button
49
+ type="button"
50
+ disabled={isSubmitting}
51
+ onClick={handleClick}
52
+ className="cursor-pointer w-full"
53
+ >
54
+ {isSubmitting ? (
55
+ <div className="flex items-center">
56
+ <Loader2 className="h-5 w-5 animate-spin" />
57
+ <span className="ml-2">Loading...</span>
58
+ </div>
59
+ ) : (
60
+ "Load Escrow"
61
+ )}
62
+ </Button>
63
+ );
64
+ };