Skip to content

Commit 01358f9

Browse files
authored
Merge pull request #19 from WhyAsh5114/create-and-fund-in-one-go
Create and fund in one go
2 parents b0d3f9b + f16c5af commit 01358f9

File tree

9 files changed

+69
-44
lines changed

9 files changed

+69
-44
lines changed

blockchain/contracts/TOTPWallet.sol

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ contract TOTPWallet is IAccount {
7575
/// @param verifier The ZK proof verifier contract address
7676
/// @param anOwner The initial owner of the wallet
7777
/// @param initialSecretHash Hash of the owner's TOTP secret
78-
constructor(IEntryPoint anEntryPoint, TOTPVerifier verifier, address anOwner, uint256 initialSecretHash) {
78+
constructor(IEntryPoint anEntryPoint, TOTPVerifier verifier, address anOwner, uint256 initialSecretHash) payable {
7979
_entryPoint = anEntryPoint;
8080
_verifier = verifier;
8181
owner = anOwner;

blockchain/generated.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ export const totpWalletAbi = [
131131
{ name: 'anOwner', internalType: 'address', type: 'address' },
132132
{ name: 'initialSecretHash', internalType: 'uint256', type: 'uint256' },
133133
],
134-
stateMutability: 'nonpayable',
134+
stateMutability: 'payable',
135135
},
136136
{ type: 'error', inputs: [], name: 'DirectExecuteDisabled' },
137137
{ type: 'error', inputs: [], name: 'ECDSAInvalidSignature' },

blockchain/test/TOTPWallet.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,21 @@ describe("TOTPWallet", function () {
4747
assert.equal(walletOwner.toLowerCase(), owner.account.address.toLowerCase());
4848
});
4949

50+
it("Should accept ETH during deployment", async function () {
51+
const mockEntryPoint = await viem.deployContract("MockEntryPoint");
52+
const fundingAmount = parseEther("1.0");
53+
54+
const totpWallet = await viem.deployContract("TOTPWallet", [
55+
mockEntryPoint.address,
56+
verifier.address,
57+
owner.account.address,
58+
testSecretHash,
59+
], { value: fundingAmount });
60+
61+
const balance = await publicClient.getBalance({ address: totpWallet.address });
62+
assert.equal(balance, fundingAmount);
63+
});
64+
5065
it("Should set the correct EntryPoint", async function () {
5166
const mockEntryPoint = await viem.deployContract("MockEntryPoint");
5267
const totpWallet = await viem.deployContract("TOTPWallet", [

frontend/public/manifest.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
"short_name": "TOTP Wallet",
44
"description": "Zero-knowledge TOTP-based account abstraction wallet",
55
"start_url": "/",
6-
"display": "fullscreen",
6+
"display": "standalone",
77
"background_color": "#000000",
88
"theme_color": "#000000",
99
"orientation": "portrait",

frontend/src/app/(routes)/dashboard/deploy/page.tsx

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,18 @@ export default function DeployPage() {
9898
</CardHeader>
9999
</Card>
100100

101-
<WalletFunding walletAddress={deployedWalletAddress} />
101+
<Card>
102+
<CardHeader>
103+
<CardTitle>Next Steps</CardTitle>
104+
<CardDescription>
105+
You can add more funds to your wallet or continue to execute
106+
transactions
107+
</CardDescription>
108+
</CardHeader>
109+
<CardContent>
110+
<WalletFunding walletAddress={deployedWalletAddress} />
111+
</CardContent>
112+
</Card>
102113

103114
<div className="flex justify-end">
104115
<Button onClick={() => router.push("/dashboard/execute")}>

frontend/src/components/authenticator-proof-generator.tsx

Lines changed: 0 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -406,37 +406,6 @@ export function AuthenticatorProofGenerator({
406406
</div>
407407
)}
408408

409-
{status === "uploaded" && (
410-
<div className="space-y-4">
411-
<div className="flex items-start gap-3 rounded-lg border border-primary/20 bg-primary/5 p-4">
412-
<CheckCircle2 className="mt-0.5 h-5 w-5 text-primary" />
413-
<div className="flex-1 text-sm">
414-
<p className="font-medium text-foreground">
415-
Proof Uploaded Successfully
416-
</p>
417-
<p className="mt-1 text-muted-foreground">
418-
The transaction device will execute the transaction
419-
automatically.
420-
</p>
421-
</div>
422-
</div>
423-
424-
<Button
425-
onClick={() => {
426-
setTxRequest(null);
427-
setTotpCode("");
428-
setProof(null);
429-
setStatus("idle");
430-
setCurrentQRIndex(0);
431-
}}
432-
variant="outline"
433-
className="w-full"
434-
>
435-
Generate Another Proof
436-
</Button>
437-
</div>
438-
)}
439-
440409
{status === "uploaded" && (
441410
<div className="space-y-4">
442411
<div className="flex items-start gap-3 rounded-lg border border-primary/20 bg-primary/5 p-4">

frontend/src/components/wallet-deployment.tsx

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import { AlertCircle, CheckCircle2, Loader2, Wallet } from "lucide-react";
44
import { useEffect, useState } from "react";
55
import { toast } from "sonner";
6-
import { type Address, isAddress } from "viem";
6+
import { type Address, isAddress, parseEther } from "viem";
77
import { useAccount } from "wagmi";
88
import { Button } from "@/components/ui/button";
99
import {
@@ -36,6 +36,7 @@ export function WalletDeployment({
3636

3737
const [entryPointAddress, setEntryPointAddress] = useState<string>("");
3838
const [verifierAddress, setVerifierAddress] = useState<string>("");
39+
const [initialFunding, setInitialFunding] = useState<string>("");
3940
const [deployedWallet, setDeployedWallet] = useState<Address | null>(null);
4041

4142
// Load default addresses on mount
@@ -86,11 +87,16 @@ export function WalletDeployment({
8687
verifierAddress: verifierAddress as Address,
8788
ownerAddress: userAddress,
8889
initialSecretHash: secretHash,
90+
initialFunding: initialFunding ? parseEther(initialFunding) : undefined,
8991
});
9092

9193
if (walletAddress) {
9294
setDeployedWallet(walletAddress);
93-
toast.success("Wallet deployed successfully!");
95+
toast.success(
96+
initialFunding
97+
? "Wallet deployed and funded successfully!"
98+
: "Wallet deployed successfully!",
99+
);
94100
onDeployed?.(walletAddress);
95101
}
96102
} catch (error) {
@@ -249,6 +255,24 @@ export function WalletDeployment({
249255
/>
250256
</div>
251257
)}
258+
259+
<div className="space-y-2">
260+
<Label htmlFor="funding">Initial Funding (ETH) - Optional</Label>
261+
<Input
262+
id="funding"
263+
type="number"
264+
step="0.001"
265+
min="0"
266+
placeholder="0.1"
267+
value={initialFunding}
268+
onChange={(e) => setInitialFunding(e.target.value)}
269+
disabled={isDeploying || !secretHash}
270+
/>
271+
<p className="text-xs text-muted-foreground">
272+
Fund your wallet during deployment to skip the separate funding
273+
step. Recommended: 0.01 ETH or more for gas fees
274+
</p>
275+
</div>
252276
</CardContent>
253277
<CardFooter>
254278
<Button
@@ -259,12 +283,14 @@ export function WalletDeployment({
259283
{isDeploying ? (
260284
<>
261285
<Loader2 className="mr-2 h-4 w-4 animate-spin" />
262-
Deploying Wallet...
286+
{initialFunding
287+
? "Deploying & Funding..."
288+
: "Deploying Wallet..."}
263289
</>
264290
) : (
265291
<>
266292
<Wallet className="mr-2 h-4 w-4" />
267-
Deploy Wallet
293+
{initialFunding ? "Deploy & Fund Wallet" : "Deploy Wallet"}
268294
</>
269295
)}
270296
</Button>

frontend/src/hooks/use-totp-wallet.ts

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ export interface DeployWalletParams {
1616
verifierAddress: Address;
1717
ownerAddress: Address;
1818
initialSecretHash: bigint;
19+
initialFunding?: bigint; // Optional initial funding amount in wei
1920
}
2021

2122
export interface ExecuteTransactionParams {
@@ -103,17 +104,20 @@ export function useTOTPWallet(): UseTOTPWalletResult {
103104
params.initialSecretHash,
104105
],
105106
gas: BigInt(5000000), // Set a reasonable gas limit for contract deployment
107+
value: params.initialFunding, // Send ETH with deployment transaction
106108
});
107109

108110
// Wait for transaction to be mined
109111
const receipt = await publicClient.waitForTransactionReceipt({ hash });
110112

111-
if (receipt.contractAddress) {
112-
setWalletAddress(receipt.contractAddress);
113-
return receipt.contractAddress;
113+
if (!receipt.contractAddress) {
114+
throw new Error("Failed to get contract address");
114115
}
115116

116-
throw new Error("Failed to get contract address");
117+
const deployedAddress = receipt.contractAddress;
118+
setWalletAddress(deployedAddress);
119+
120+
return deployedAddress;
117121
} catch (err) {
118122
const error = err instanceof Error ? err : new Error(String(err));
119123
setError(error);

frontend/src/lib/contract-addresses.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ export const CONTRACT_ADDRESSES = {
99
// Sepolia Testnet
1010
sepolia: {
1111
entryPoint: "0x0000000071727De22E5E9d8BAf0edAc6f37da032",
12-
verifier: "0xd3961aeac5f456a7efa3751a072a9ae5748c754b",
12+
verifier: "0xed0a886d6fe34805048541de4b9ac70ce259f113",
1313
},
1414
// Hardhat Local
1515
hardhat: {

0 commit comments

Comments
 (0)