Skip to content

Commit 311a042

Browse files
committed
mig01
1 parent d37992f commit 311a042

File tree

18 files changed

+2951
-153
lines changed

18 files changed

+2951
-153
lines changed

package-lock.json

Lines changed: 381 additions & 39 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
"@meshsdk/core-cst": "^1.9.0-beta.19",
3030
"@meshsdk/react": "^1.9.0-beta.18",
3131
"@octokit/core": "^6.1.2",
32-
"@prisma/client": "^6.4.1",
32+
"@prisma/client": "^6.17.1",
3333
"@radix-ui/react-accordion": "^1.2.0",
3434
"@radix-ui/react-checkbox": "^1.1.1",
3535
"@radix-ui/react-collapsible": "^1.1.0",
@@ -111,7 +111,7 @@
111111
"postcss": "^8.4.39",
112112
"prettier": "^3.3.2",
113113
"prettier-plugin-tailwindcss": "^0.6.5",
114-
"prisma": "^6.4.1",
114+
"prisma": "^6.17.1",
115115
"tailwindcss": "^3.4.3",
116116
"ts-jest": "^29.4.4",
117117
"typescript": "^5.5.3"
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
-- AlterTable
2+
ALTER TABLE "Wallet" ADD COLUMN "migrationTargetWalletId" TEXT;
3+

prisma/schema.prisma

Lines changed: 16 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,3 @@
1-
// This is your Prisma schema file,
2-
// learn more about it in the docs: https://pris.ly/d/prisma-schema
3-
41
generator client {
52
provider = "prisma-client-js"
63
}
@@ -19,19 +16,20 @@ model User {
1916
}
2017

2118
model Wallet {
22-
id String @id @default(cuid())
23-
name String
24-
description String?
25-
signersAddresses String[]
26-
signersStakeKeys String[]
27-
signersDescriptions String[]
28-
numRequiredSigners Int?
29-
verified String[]
30-
scriptCbor String
31-
stakeCredentialHash String?
32-
type String
33-
isArchived Boolean @default(false)
34-
clarityApiKey String?
19+
id String @id @default(cuid())
20+
name String
21+
description String?
22+
signersAddresses String[]
23+
signersStakeKeys String[]
24+
signersDescriptions String[]
25+
numRequiredSigners Int?
26+
verified String[]
27+
scriptCbor String
28+
stakeCredentialHash String?
29+
type String
30+
isArchived Boolean @default(false)
31+
clarityApiKey String?
32+
migrationTargetWalletId String?
3533
}
3634

3735
model Transaction {
@@ -97,13 +95,13 @@ model Ballot {
9795

9896
model Proxy {
9997
id String @id @default(cuid())
100-
walletId String? // Optional - can be linked to wallet or user
101-
userId String? // Optional - can be linked to user directly
98+
walletId String?
10299
proxyAddress String
103100
authTokenId String
104101
paramUtxo String
105102
description String?
106103
isActive Boolean @default(true)
107104
createdAt DateTime @default(now())
108105
updatedAt DateTime @updatedAt
106+
userId String?
109107
}

src/components/multisig/proxy/ProxyControl.tsx

Lines changed: 92 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,13 @@ import { toast } from "@/hooks/use-toast";
77
import { getTxBuilder } from "@/utils/get-tx-builder";
88
import useAppWallet from "@/hooks/useAppWallet";
99
import { api } from "@/utils/api";
10+
import useTransaction from "@/hooks/useTransaction";
1011
import ProxyOverview from "./ProxyOverview";
1112
import ProxySetup from "./ProxySetup";
1213
import ProxySpend from "./ProxySpend";
14+
import UTxOSelector from "@/components/pages/wallet/new-transaction/utxoSelector";
15+
import { getProvider } from "@/utils/get-provider";
16+
import { MeshTxBuilder, UTxO } from "@meshsdk/core";
1317

1418
import { Alert, AlertDescription } from "@/components/ui/alert";
1519
import { Dialog, DialogContent, DialogHeader, DialogTitle } from "@/components/ui/dialog";
@@ -25,7 +29,7 @@ interface ProxyOutput {
2529
}
2630

2731
interface ProxySetupResult {
28-
tx: string;
32+
tx: MeshTxBuilder;
2933
paramUtxo: { txHash: string; outputIndex: number };
3034
authTokenId: string;
3135
proxyAddress: string;
@@ -38,12 +42,9 @@ export default function ProxyControl() {
3842
const network = useSiteStore((state) => state.network);
3943
const { appWallet } = useAppWallet();
4044
const ctx = api.useUtils();
45+
const { newTransaction } = useTransaction();
46+
4147

42-
const { mutateAsync: createTransaction } = api.transaction.createTransaction.useMutation({
43-
onSuccess: () => {
44-
void ctx.transaction.getPendingTransactions.invalidate();
45-
},
46-
});
4748

4849
const { mutateAsync: createProxy } = api.proxy.createProxy.useMutation({
4950
onSuccess: () => {
@@ -63,14 +64,27 @@ export default function ProxyControl() {
6364
{ enabled: !!userAddress && !appWallet?.id }
6465
);
6566

66-
const { data: proxies, refetch: refetchProxies } = api.proxy.getProxiesByUserOrWallet.useQuery(
67+
const { data: proxies, refetch: refetchProxies, isLoading: proxiesLoading, error: proxiesError } = api.proxy.getProxiesByUserOrWallet.useQuery(
6768
{
6869
walletId: appWallet?.id || undefined,
6970
userAddress: userAddress || undefined,
7071
},
7172
{ enabled: !!(appWallet?.id || userAddress) }
7273
);
7374

75+
// Debug logging for proxy loading
76+
useEffect(() => {
77+
console.log("Proxy loading debug:", {
78+
appWalletId: appWallet?.id,
79+
userAddress,
80+
enabled: !!(appWallet?.id || userAddress),
81+
proxiesLoading,
82+
proxiesError,
83+
proxiesCount: proxies?.length || 0,
84+
proxies: proxies
85+
});
86+
}, [appWallet?.id, userAddress, proxiesLoading, proxiesError, proxies]);
87+
7488
// State management
7589
const [proxyContract, setProxyContract] = useState<MeshProxyContract | null>(null);
7690
const [proxyBalance, setProxyBalance] = useState<Array<{ unit: string; quantity: string }>>([]);
@@ -87,7 +101,7 @@ export default function ProxyControl() {
87101
paramUtxo?: { txHash: string; outputIndex: number };
88102
authTokenId?: string;
89103
proxyAddress?: string;
90-
txHex?: string;
104+
txHex?: MeshTxBuilder;
91105
description?: string;
92106
}>({});
93107

@@ -105,6 +119,25 @@ export default function ProxyControl() {
105119
{ address: "", unit: "lovelace", amount: "" }
106120
]);
107121

122+
// UTxO selection state (UI only). We will still pass all UTxOs from provider to contract.
123+
const [selectedUtxos, setSelectedUtxos] = useState<UTxO[]>([]);
124+
const [manualSelected, setManualSelected] = useState<boolean>(false);
125+
126+
// Helper to resolve inputs for multisig controlled txs
127+
const getMsInputs = useCallback(async (): Promise<{ utxos: UTxO[]; walletAddress: string }> => {
128+
if (!appWallet?.address) {
129+
throw new Error("Multisig wallet address not available");
130+
}
131+
const provider = getProvider(network);
132+
const utxos = await provider.fetchAddressUTxOs(appWallet.address);
133+
if (!utxos || utxos.length === 0) {
134+
throw new Error("No UTxOs found at multisig wallet address");
135+
}
136+
console.log("utxos", utxos);
137+
console.log("walletAddress", appWallet.address);
138+
return { utxos, walletAddress: appWallet.address };
139+
}, [appWallet?.address, network]);
140+
108141
// Initialize proxy contract
109142
useEffect(() => {
110143
if (connected && wallet && userAddress) {
@@ -116,7 +149,8 @@ export default function ProxyControl() {
116149
wallet: wallet,
117150
networkId: network,
118151
},
119-
{}
152+
{},
153+
appWallet?.scriptCbor || undefined,
120154
);
121155
setProxyContract(contract);
122156
} catch (error) {
@@ -172,8 +206,10 @@ export default function ProxyControl() {
172206
// Reset proxy contract state to prevent policy ID conflicts
173207
proxyContract.reset();
174208

175-
const result: ProxySetupResult = await proxyContract.setupProxy();
176-
209+
// Use multisig wallet inputs: pass all UTxOs, first >=5 ADA as collateral, and ms wallet address
210+
const { utxos, collateral, walletAddress } = await getMsInputs();
211+
const result: ProxySetupResult = await proxyContract.setupProxy(utxos, walletAddress);
212+
177213
setSetupData({
178214
paramUtxo: result.paramUtxo,
179215
authTokenId: result.authTokenId,
@@ -217,9 +253,21 @@ export default function ProxyControl() {
217253
setSetupLoading(true);
218254
setLoading(true);
219255

220-
// Sign and submit the transaction
221-
const signedTx = await wallet.signTx(setupData.txHex, true);
222-
await wallet.submitTx(signedTx);
256+
// If msCbor is set, route through useTransaction hook to create a signable
257+
if (appWallet?.scriptCbor && setupData.txHex) {
258+
259+
await newTransaction({
260+
txBuilder: setupData.txHex,
261+
description: setupData.description,
262+
toastMessage: "Proxy setup transaction created",
263+
});
264+
} else if (setupData.txHex) {
265+
// Sign and submit the transaction
266+
const signedTx = await wallet.signTx(await setupData.txHex.complete(), true);
267+
await wallet.submitTx(signedTx);
268+
} else {
269+
throw new Error("No transaction to submit");
270+
}
223271

224272
// Store proxy information in the database
225273
if (!appWallet?.id && !userAddress) {
@@ -430,7 +478,7 @@ export default function ProxyControl() {
430478
// Handle proxy selection
431479
const handleProxySelection = useCallback(async (proxyId: string) => {
432480
setSelectedProxy(proxyId);
433-
const proxy = proxies?.find(p => p.id === proxyId);
481+
const proxy = proxies?.find((p: any) => p.id === proxyId);
434482
if (proxy) {
435483
const balance = await getProxyBalance(proxy.proxyAddress);
436484
setSelectedProxyBalance(balance);
@@ -477,7 +525,7 @@ export default function ProxyControl() {
477525
setLoading(true);
478526

479527
// Get the selected proxy
480-
const proxy = proxies?.find(p => p.id === selectedProxy);
528+
const proxy = proxies?.find((p: any) => p.id === selectedProxy);
481529
if (!proxy) {
482530
throw new Error("Selected proxy not found");
483531
}
@@ -491,21 +539,23 @@ export default function ProxyControl() {
491539
},
492540
{
493541
paramUtxo: JSON.parse(proxy.paramUtxo),
494-
}
542+
},
543+
appWallet?.scriptCbor || undefined,
495544
);
496545
selectedProxyContract.proxyAddress = proxy.proxyAddress;
497546

498-
const txHex = await selectedProxyContract.spendProxySimple(validOutputs);
499-
500-
// Sign and submit the transaction
501-
const signedTx = await wallet.signTx(txHex, true);
502-
await wallet.submitTx(signedTx);
503-
504-
toast({
505-
title: "Success",
506-
description: "Proxy spend transaction submitted successfully",
507-
variant: "default",
508-
});
547+
// Pass multisig inputs to spend as well
548+
const { utxos, walletAddress } = await getMsInputs();
549+
const txHex = await selectedProxyContract.spendProxySimple(validOutputs, utxos, walletAddress);
550+
if (appWallet?.scriptCbor) {
551+
await newTransaction({
552+
txBuilder: txHex,
553+
description: "Proxy spend transaction",
554+
toastMessage: "Proxy spend transaction created",
555+
});
556+
} else {
557+
await wallet.submitTx(await txHex.complete());
558+
}
509559

510560
// Refresh balance after successful spend
511561
await handleProxySelection(selectedProxy);
@@ -702,6 +752,20 @@ export default function ProxyControl() {
702752
onRefreshAllBalances={refreshAllBalances}
703753
/>
704754

755+
{/* UTxO Selector for visibility/control. Contract uses all UTxOs from provider. */}
756+
{appWallet && (
757+
<div className="mt-2">
758+
<UTxOSelector
759+
appWallet={appWallet}
760+
network={network}
761+
onSelectionChange={(utxos, manual) => {
762+
setSelectedUtxos(utxos);
763+
setManualSelected(manual);
764+
}}
765+
/>
766+
</div>
767+
)}
768+
705769
</div>
706770
</CardContent>
707771
)}

src/components/multisig/proxy/ProxySetup.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,15 @@ import {
1313
Play,
1414
Check
1515
} from "lucide-react";
16+
import { MeshTxBuilder } from "@meshsdk/core";
1617

1718
interface ProxySetupProps {
1819
setupStep: number;
1920
setupData: {
2021
paramUtxo?: { txHash: string; outputIndex: number };
2122
authTokenId?: string;
2223
proxyAddress?: string;
23-
txHex?: string;
24+
txHex?: MeshTxBuilder;
2425
description?: string;
2526
};
2627
setupLoading: boolean;

0 commit comments

Comments
 (0)