Skip to content

Commit 06548ad

Browse files
committed
s12
1 parent 7ce6ef0 commit 06548ad

24 files changed

+2664
-841
lines changed

prisma/schema.prisma

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,3 +123,23 @@ model BalanceSnapshot {
123123
isArchived Boolean
124124
snapshotDate DateTime @default(now())
125125
}
126+
127+
model Migration {
128+
id String @id @default(cuid())
129+
originalWalletId String // The wallet being migrated from
130+
newWalletId String? // The new wallet being created (null until created)
131+
ownerAddress String // The user who initiated the migration
132+
currentStep Int @default(0) // 0=pre-checks, 1=create wallet, 2=proxy setup, 3=transfer funds, 4=complete
133+
status String @default("pending") // pending, in_progress, completed, failed, cancelled
134+
migrationData Json? // Store any additional migration-specific data
135+
errorMessage String? // Store error details if migration fails
136+
createdAt DateTime @default(now())
137+
updatedAt DateTime @updatedAt
138+
completedAt DateTime?
139+
140+
// Indexes for efficient querying
141+
@@index([ownerAddress])
142+
@@index([originalWalletId])
143+
@@index([status])
144+
@@index([createdAt])
145+
}

src/components/common/overall-layout/layout.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -296,6 +296,7 @@ export default function RootLayout({
296296
</div>
297297
</header>
298298

299+
299300
<main className="relative flex flex-1 flex-col gap-4 overflow-y-auto overflow-x-hidden p-4 md:p-8">
300301
<WalletErrorBoundary
301302
fallback={

src/components/common/overall-layout/mobile-wrappers/wallet-data-loader-wrapper.tsx

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import { Asset } from "@meshsdk/core";
1111
import { getDRepIds } from "@meshsdk/core-cst";
1212
import { BlockfrostDrepInfo } from "@/types/governance";
1313
import { Button } from "@/components/ui/button";
14+
import { useProxyActions } from "@/lib/zustand/proxy";
1415

1516
interface WalletDataLoaderWrapperProps {
1617
mode: "button" | "menu-item";
@@ -47,6 +48,7 @@ export default function WalletDataLoaderWrapper({
4748
const setWalletAssetMetadata = useWalletsStore(
4849
(state) => state.setWalletAssetMetadata,
4950
);
51+
const { fetchProxyBalance, fetchProxyDrepInfo, setProxies } = useProxyActions();
5052

5153
const setDrepInfo = useWalletsStore((state) => state.setDrepInfo);
5254

@@ -179,6 +181,51 @@ export default function WalletDataLoaderWrapper({
179181
}
180182
}
181183

184+
async function fetchProxyData() {
185+
if (appWallet?.id && appWallet?.scriptCbor) {
186+
try {
187+
// Get proxies from API
188+
const proxies = await ctx.proxy.getProxiesByUserOrWallet.fetch({
189+
walletId: appWallet.id,
190+
});
191+
192+
193+
// First, add proxies to the store
194+
setProxies(appWallet.id, proxies);
195+
196+
// Fetch balance and DRep info for each proxy
197+
for (const proxy of proxies) {
198+
try {
199+
200+
// Fetch balance
201+
await fetchProxyBalance(
202+
appWallet.id,
203+
proxy.id,
204+
proxy.proxyAddress,
205+
network.toString()
206+
);
207+
208+
// Fetch DRep info
209+
await fetchProxyDrepInfo(
210+
appWallet.id,
211+
proxy.id,
212+
proxy.proxyAddress,
213+
proxy.authTokenId,
214+
appWallet.scriptCbor,
215+
network.toString(),
216+
proxy.paramUtxo
217+
);
218+
219+
} catch (error) {
220+
console.error(`WalletDataLoaderWrapper: Error fetching data for proxy ${proxy.id}:`, error);
221+
}
222+
}
223+
} catch (error) {
224+
console.error("WalletDataLoaderWrapper: Error fetching proxy data:", error);
225+
}
226+
}
227+
}
228+
182229
async function refreshWallet() {
183230
if (fetchingTransactions.current) return;
184231

@@ -188,6 +235,7 @@ export default function WalletDataLoaderWrapper({
188235
await getTransactionsOnChain();
189236
await getWalletAssets();
190237
await getDRepInfo();
238+
await fetchProxyData(); // Fetch proxy data
191239
void ctx.transaction.getPendingTransactions.invalidate();
192240
void ctx.transaction.getAllTransactions.invalidate();
193241
// Also refresh proxy data
@@ -206,6 +254,9 @@ export default function WalletDataLoaderWrapper({
206254
if (appWallet && prevWalletIdRef.current !== appWallet.id) {
207255
refreshWallet();
208256
prevWalletIdRef.current = appWallet.id;
257+
} else if (appWallet) {
258+
// If wallet exists but we already have data, still fetch proxy data
259+
fetchProxyData();
209260
}
210261
}, [appWallet]);
211262

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
import { useEffect } from "react";
2+
import useAppWallet from "@/hooks/useAppWallet";
3+
import { useProxyStore, useProxyData, useProxyActions } from "@/lib/zustand/proxy";
4+
import { useSiteStore } from "@/lib/zustand/site";
5+
import { api } from "@/utils/api";
6+
7+
export default function ProxyDataLoader() {
8+
const { appWallet } = useAppWallet();
9+
const network = useSiteStore((state) => state.network);
10+
const { proxies, loading, error } = useProxyData(appWallet?.id);
11+
const {
12+
setProxies,
13+
fetchProxyBalance,
14+
fetchProxyDrepInfo,
15+
clearProxyData
16+
} = useProxyActions();
17+
18+
19+
20+
// Get proxies from API
21+
const { data: apiProxies, refetch: refetchProxies, isLoading: apiLoading } = api.proxy.getProxiesByUserOrWallet.useQuery(
22+
{
23+
walletId: appWallet?.id || undefined,
24+
},
25+
{
26+
enabled: !!appWallet?.id,
27+
refetchOnWindowFocus: false,
28+
staleTime: 30000, // 30 seconds
29+
}
30+
);
31+
32+
// Update store when API data changes
33+
useEffect(() => {
34+
if (apiProxies && appWallet?.id) {
35+
const proxyData = apiProxies.map(proxy => ({
36+
id: proxy.id,
37+
proxyAddress: proxy.proxyAddress,
38+
authTokenId: proxy.authTokenId,
39+
paramUtxo: proxy.paramUtxo,
40+
description: proxy.description,
41+
isActive: proxy.isActive,
42+
createdAt: new Date(proxy.createdAt),
43+
lastUpdated: Date.now(),
44+
}));
45+
46+
setProxies(appWallet.id, proxyData);
47+
}
48+
}, [apiProxies, appWallet?.id, setProxies]);
49+
50+
// Fetch additional data for each proxy
51+
useEffect(() => {
52+
53+
if (proxies.length > 0 && appWallet?.id && appWallet?.scriptCbor) {
54+
proxies.forEach(async (proxy) => {
55+
// Only fetch if we don't have recent data (older than 5 minutes)
56+
const isStale = !proxy.lastUpdated || (Date.now() - proxy.lastUpdated) > 5 * 60 * 1000;
57+
58+
59+
if (isStale) {
60+
try {
61+
62+
// Fetch balance
63+
await fetchProxyBalance(appWallet.id, proxy.id, proxy.proxyAddress, network.toString());
64+
65+
// Fetch DRep info
66+
await fetchProxyDrepInfo(
67+
appWallet.id,
68+
proxy.id,
69+
proxy.proxyAddress,
70+
proxy.authTokenId,
71+
appWallet.scriptCbor,
72+
network.toString(),
73+
proxy.paramUtxo
74+
);
75+
76+
77+
} catch (error) {
78+
console.error(`Error fetching data for proxy ${proxy.id}:`, error);
79+
}
80+
}
81+
});
82+
}
83+
}, [proxies, appWallet?.id, appWallet?.scriptCbor, network, fetchProxyBalance, fetchProxyDrepInfo]);
84+
85+
// Clear proxy data when wallet changes
86+
useEffect(() => {
87+
return () => {
88+
if (appWallet?.id) {
89+
clearProxyData(appWallet.id);
90+
}
91+
};
92+
}, [appWallet?.id, clearProxyData]);
93+
94+
// Expose refetch function for manual refresh
95+
useEffect(() => {
96+
// Store refetch function in window for global access if needed
97+
if (typeof window !== 'undefined') {
98+
(window as any).refetchProxyData = refetchProxies;
99+
}
100+
}, [refetchProxies]);
101+
102+
return null; // This is a data loader component, no UI
103+
}

src/components/common/overall-layout/wallet-data-loader.tsx

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { useWalletsStore } from "@/lib/zustand/wallets";
77
import { api } from "@/utils/api";
88
import { OnChainTransaction, TxInfo } from "@/types/transaction";
99
import { useSiteStore } from "@/lib/zustand/site";
10+
import { useProxyActions } from "@/lib/zustand/proxy";
1011

1112
export default function WalletDataLoader() {
1213
const { appWallet } = useAppWallet();
@@ -19,6 +20,7 @@ export default function WalletDataLoader() {
1920
const ctx = api.useUtils();
2021
const network = useSiteStore((state) => state.network);
2122
const setRandomState = useSiteStore((state) => state.setRandomState);
23+
const { fetchProxyBalance, fetchProxyDrepInfo, setProxies } = useProxyActions();
2224

2325
async function fetchUtxos() {
2426
if (appWallet) {
@@ -53,10 +55,64 @@ export default function WalletDataLoader() {
5355
}
5456
}
5557

58+
async function fetchProxyData() {
59+
if (appWallet?.id && appWallet?.scriptCbor) {
60+
console.log("WalletDataLoader: Fetching proxy data for wallet", appWallet.id);
61+
62+
try {
63+
// Get proxies from API
64+
const proxies = await ctx.proxy.getProxiesByUserOrWallet.fetch({
65+
walletId: appWallet.id,
66+
});
67+
68+
console.log("WalletDataLoader: Found proxies", proxies);
69+
70+
// First, add proxies to the store
71+
setProxies(appWallet.id, proxies);
72+
73+
// Fetch balance and DRep info for each proxy
74+
for (const proxy of proxies) {
75+
try {
76+
console.log(`WalletDataLoader: Fetching data for proxy ${proxy.id}`);
77+
78+
// Fetch balance
79+
await fetchProxyBalance(
80+
appWallet.id,
81+
proxy.id,
82+
proxy.proxyAddress,
83+
network.toString()
84+
);
85+
86+
// Fetch DRep info
87+
await fetchProxyDrepInfo(
88+
appWallet.id,
89+
proxy.id,
90+
proxy.proxyAddress,
91+
proxy.authTokenId,
92+
appWallet.scriptCbor,
93+
network.toString(),
94+
proxy.paramUtxo
95+
);
96+
97+
console.log(`WalletDataLoader: Successfully fetched data for proxy ${proxy.id}`);
98+
} catch (error) {
99+
console.error(`WalletDataLoader: Error fetching data for proxy ${proxy.id}:`, error);
100+
}
101+
}
102+
} catch (error) {
103+
console.error("WalletDataLoader: Error fetching proxy data:", error);
104+
}
105+
}
106+
}
107+
56108
async function refreshWallet() {
109+
console.log("WalletDataLoader: refreshWallet called");
57110
setLoading(true);
58111
await fetchUtxos();
59112
await getTransactionsOnChain();
113+
console.log("WalletDataLoader: About to fetch proxy data");
114+
await fetchProxyData(); // Fetch proxy data
115+
console.log("WalletDataLoader: Finished fetching proxy data");
60116
void ctx.transaction.getPendingTransactions.invalidate();
61117
void ctx.transaction.getAllTransactions.invalidate();
62118
// Also refresh proxy data
@@ -66,8 +122,19 @@ export default function WalletDataLoader() {
66122
}
67123

68124
useEffect(() => {
125+
console.log("WalletDataLoader: useEffect triggered", {
126+
hasAppWallet: !!appWallet,
127+
walletId: appWallet?.id,
128+
hasUtxos: appWallet?.id ? walletsUtxos[appWallet.id] !== undefined : false
129+
});
130+
69131
if (appWallet && walletsUtxos[appWallet?.id] === undefined) {
132+
console.log("WalletDataLoader: Calling refreshWallet");
70133
refreshWallet();
134+
} else if (appWallet) {
135+
// If wallet exists but we already have UTxOs, still fetch proxy data
136+
console.log("WalletDataLoader: Calling fetchProxyData directly");
137+
fetchProxyData();
71138
}
72139
}, [appWallet]);
73140

src/components/multisig/inspect-multisig-script.tsx

Lines changed: 31 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -88,28 +88,37 @@ export default function InspectMultisigScript({
8888
}
8989

9090
return (
91-
<CardUI title="Native Script" cardClassName="col-span-2">
92-
{mWallet.stakingEnabled() && <RowLabelInfo
93-
label="Address"
94-
value={<Code>{mWallet.getScript().address}</Code>}
95-
copyString={mWallet.getScript().address}
96-
/>}
97-
<RowLabelInfo label="Balance" value={<Code>{`${balance} ₳`}</Code>} />
98-
{mWallet.stakingEnabled() && (
99-
<RowLabelInfo
100-
label="Stake Address"
101-
value={<Code>{mWallet.getStakeAddress()}</Code>}
102-
copyString={mWallet.getStakeAddress()}
103-
/>
104-
)}
105-
{/* add pending rewards like balance */}
106-
{mWallet.isGovernanceEnabled() && <RowLabelInfo
107-
label="dRep ID"
108-
value={<Code>{mWallet.getDRepId()}</Code>}
109-
copyString={mWallet.getDRepId()}
110-
/>}
91+
<div className="col-span-2 w-full rounded-xl border border-zinc-200 bg-white text-zinc-950 shadow dark:border-zinc-800 dark:bg-zinc-950 dark:text-zinc-50">
92+
<div className="flex flex-row items-center justify-between space-y-0 pb-2 p-6">
93+
<h3 className="text-xl font-medium">Native Script</h3>
94+
</div>
95+
<div className="p-6 pt-0">
96+
<div className="mt-1 flex flex-col gap-2">
97+
<div className="mt-1 flex flex-col gap-2">
98+
{mWallet.stakingEnabled() && <RowLabelInfo
99+
label="Address"
100+
value={<Code>{mWallet.getScript().address}</Code>}
101+
copyString={mWallet.getScript().address}
102+
/>}
103+
<RowLabelInfo label="Balance" value={<Code>{`${balance} ₳`}</Code>} />
104+
{mWallet.stakingEnabled() && (
105+
<RowLabelInfo
106+
label="Stake Address"
107+
value={<Code>{mWallet.getStakeAddress()}</Code>}
108+
copyString={mWallet.getStakeAddress()}
109+
/>
110+
)}
111+
{/* add pending rewards like balance */}
112+
{mWallet.isGovernanceEnabled() && <RowLabelInfo
113+
label="dRep ID"
114+
value={<Code>{mWallet.getDRepId()}</Code>}
115+
copyString={mWallet.getDRepId()}
116+
/>}
111117

112-
<Carousel slides={slides} />
113-
</CardUI>
118+
<Carousel slides={slides} />
119+
</div>
120+
</div>
121+
</div>
122+
</div>
114123
);
115124
}

0 commit comments

Comments
 (0)