Skip to content

Commit

Permalink
feat: fetch wallet info
Browse files Browse the repository at this point in the history
  • Loading branch information
ChiHaoLu committed Nov 5, 2024
1 parent 34ff744 commit 75b190a
Show file tree
Hide file tree
Showing 6 changed files with 194 additions and 11 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
"start": "next start"
},
"dependencies": {
"@consenlabs/imaccount-sdk": "^0.1.28",
"@consenlabs/imaccount-sdk": "^0.1.29",
"next": "^13.0.0",
"react": "^18.0.0",
"react-dom": "^18.0.0",
Expand Down
67 changes: 61 additions & 6 deletions pages/explorer.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
import React, { useState } from "react";
import { Address, formatEther, fromHex, Hex, zeroAddress } from "viem";
import { formatEther, fromHex, Hex, zeroAddress } from "viem";
import {
getPublicClient,
INFRA_ADDRESS,
BundlerMode,
BundlerProvider,
BundlerUserOperationData,
PackedUserOperation,
wrap,
} from "@consenlabs/imaccount-sdk";
import { UserOpReceipt } from "../types/receipt";
import Header from "./header";
Expand All @@ -23,9 +26,13 @@ const Explorer = () => {
process.env.NEXT_PUBLIC_RPC_URL ??
"https://<chain_prefix>.g.alchemy.com/v2/<your_api_key>"
);
const [chainName, setChainName] = useState<string|null>()
const [userOpReceipt, setUserOpReceipt] = useState<UserOpReceipt | null>(
null
);
const [userOpInfo, setUserOpInfo] = useState<PackedUserOperation | null>(
null
);
const [fetching, setFetching] = useState(false);

const isFetchDisabled = !userOpHash || !ALCHEMY_RPC_URL;
Expand Down Expand Up @@ -70,12 +77,14 @@ const Explorer = () => {
if (!ALCHEMY_RPC_URL) return "https://";

const provider = getPublicClient(ALCHEMY_RPC_URL);
if (!chainName || chainName === "") {
setChainName(provider.chain?.name);
}
const explorerLink = provider.chain?.blockExplorers?.default.url;

if (!explorerLink) return "https://";

const dataLink = explorerLink + type + address;
console.log(explorerLink + type + address);
return dataLink;
};

Expand All @@ -93,6 +102,9 @@ const Explorer = () => {
});

try {
const info = await bundler.getUserOperationByHash(userOpHash);
setUserOpInfo(wrap(info.userOperation));

const receipt = await bundler.getUserOperationReceipt(userOpHash);
const completeReceipt = mapToUserOpReceipt(receipt);
setUserOpReceipt(completeReceipt);
Expand Down Expand Up @@ -136,8 +148,11 @@ const Explorer = () => {
</button>
{userOpReceipt && (
<div className="explorer-result">
<h3>User Operation Info:</h3>
<h3>Overview</h3>
<div className="data-section">
<div>
<span className="label">Chain</span> {chainName}
</div>
<div>
<span className="label">UserOp Hash</span>{" "}
{userOpReceipt.userOpHash}
Expand Down Expand Up @@ -179,7 +194,9 @@ const Explorer = () => {
</div>
<div>
<span className="label">Gas Cost</span>{" "}
{userOpReceipt.actualGasCost} ETH
{userOpReceipt.paymaster === zeroAddress
? `${userOpReceipt.actualGasCost} ETH`
: `Paid ERC-20 token value approaching to ${userOpReceipt.actualGasCost} ETH`}
</div>
<div>
<span className="label">Gas Used</span>{" "}
Expand Down Expand Up @@ -236,8 +253,46 @@ const Explorer = () => {
</a>
</div>
</div>

<h3>UserOp Detail</h3>
<div className="data-section">
<div>
<span className="label">Sender</span> {userOpInfo?.sender}
</div>
<div>
<span className="label">Nonce</span> {String(userOpInfo?.nonce)}
</div>
<div>
<span className="label">Initcode</span> {""}
<div className="data-box">{userOpInfo?.initCode}</div>
</div>
<div>
<span className="label">CallData</span> {""}
<div className="data-box">{userOpInfo?.callData}</div>
</div>
<div>
<span className="label">AccountGasLimits</span>{" "}
{userOpInfo?.accountGasLimits}
</div>
<div>
<span className="label">PreVerificationGas</span>{" "}
{String(userOpInfo?.preVerificationGas)}
</div>
<div>
<span className="label">GasFees</span> {userOpInfo?.gasFees}
</div>
<div>
<span className="label">PaymasterAndData</span>{" "}
<div className="data-box">{userOpInfo?.paymasterAndData}</div>
</div>
<div>
<span className="label">Signature</span>{" "}
<div className="data-box">{userOpInfo?.signature}</div>
</div>
</div>

<h3>Event Logs</h3>
<div className="data-section">
<h4>Logs</h4>
{userOpReceipt.logs &&
userOpReceipt.logs.map((log: any, index: number) => (
<div key={index} className="log-entry">
Expand All @@ -262,7 +317,7 @@ const Explorer = () => {
))}
</div>

<h4>Whole Receipt in JSON</h4>
<h3>Whole Receipt in JSON</h3>
<pre>{JSON.stringify(userOpReceipt, null, 2)}</pre>
</div>
)}
Expand Down
21 changes: 21 additions & 0 deletions pages/footer.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import React from "react";

const Footer = () => {
return (
<div>
<h3>Project Dependencies</h3>
<p>
consenlabs@/imaccount-sdk:{" "}
<a
href="https://github.com/consenlabs/imaccount-sdk"
target="_blank"
rel="noopener noreferrer"
>
v0.1.29
</a>
</p>
</div>
);
};

export default Footer;
102 changes: 102 additions & 0 deletions pages/imaccount-info.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
import React, { useState } from "react";
import {
logEntryInfo,
logAccountInfo,
getPublicClient,
InfoType,
} from "@consenlabs/imaccount-sdk";
import { Address } from "viem";
import Header from "./header";

enum AddressType {
Entry = "Entry",
Account = "Account",
}

const AccountInfo = () => {
const [address, setAddress] = useState<Address>(
"0xea67ba18ab79c208369f7f40cf21a27c41f605f2"
);
const [type, setType] = useState<AddressType>(AddressType.Entry);
const [ALCHEMY_RPC_URL, setALCHEMY_RPC_URL] = useState(
process.env.NEXT_PUBLIC_RPC_URL ??
"https://<chain_prefix>.g.alchemy.com/v2/<your_api_key>"
);
const [fetching, setFetching] = useState(false);
const [info, setInfo] = useState<InfoType | null>();

const isFetchDisabled = !address || !type || !ALCHEMY_RPC_URL;

const getWalletInfo = async () => {
if (!address || !type || !ALCHEMY_RPC_URL) {
alert("Please fill in all required fields.");
return;
}

const provider = getPublicClient(ALCHEMY_RPC_URL);
setFetching(true);

try {
let res: InfoType | null;
if (type === AddressType.Account) {
res = await logAccountInfo(provider, address);
} else {
res = await logEntryInfo(provider, address);
}
setInfo(res);
} catch (error) {
console.error(error);
alert(`Fetching failed.\n${error}`);
setInfo(null);
} finally {
setFetching(false);
}
};

return (
<div>
<Header />
<h2>imToken AA Wallet Infomation</h2>
<div className="warning-banner">
<p>It is an experimental feature. Please use it cautiously.</p>
</div>
<div>
<h4>Address</h4>
<label>
<input
type="text"
value={address}
onChange={(e) => setAddress(e.target.value as Address)}
required
/>
</label>
<h4>Contract Type</h4>
<label>
<select
value={type}
onChange={(e) => setType(e.target.value as AddressType)}
>
{Object.values(AddressType).map((type) => (
<option key={type} value={type}>
{type}
</option>
))}
</select>
</label>
</div>
<div>
<button onClick={getWalletInfo} disabled={fetching || isFetchDisabled}>
{fetching ? "Fetching..." : "Fetch Info"}
</button>
{info && (
<div>
<h3>Wallet Infomation</h3>
<pre>{JSON.stringify(info, null, 2)}</pre>
</div>
)}
</div>
</div>
);
};

export default AccountInfo;
5 changes: 5 additions & 0 deletions pages/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import React from "react";
import Link from "next/link";

import Header from "./header";
import Footer from "./footer";

const Home = () => {
return (
Expand All @@ -14,7 +15,11 @@ const Home = () => {
<Link href="/debugger">
<div className="link">Go to 4337 Debugger</div>
</Link>
<Link href="/imaccount-info">
<div className="link">imToken AA Wallet Infomation</div>
</Link>
</div>
<Footer />
</div>
);
};
Expand Down
8 changes: 4 additions & 4 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -306,10 +306,10 @@
resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39"
integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==

"@consenlabs/imaccount-sdk@^0.1.28":
version "0.1.28"
resolved "https://npm.pkg.github.com/download/@consenlabs/imaccount-sdk/0.1.28/e82fe79a2ffdc5eb6e88b6a5a626be1206394036#e82fe79a2ffdc5eb6e88b6a5a626be1206394036"
integrity sha512-jxvW5kBpnTDOPOlY6AL70vyIrEoFv1SpRvGglKHalhqH7DU9072J3r9GPOKM8jwSg8JiT5e3Lco+dZlf2/6kvQ==
"@consenlabs/imaccount-sdk@^0.1.29":
version "0.1.29"
resolved "https://npm.pkg.github.com/download/@consenlabs/imaccount-sdk/0.1.29/852bcba07fe3831a45cbf820abd6dbe6e67f6c3a#852bcba07fe3831a45cbf820abd6dbe6e67f6c3a"
integrity sha512-mvL/LpJU8BMh8H7LczO0uVWEOB2YynDVK3kTpsV3B/HU9xkJ9SbAKXLFzWzpQbiqaR8UZNBVvbAk6OXcnx1qOg==
dependencies:
"@simplewebauthn/server" "^10.0.1"
dotenv "^16.4.5"
Expand Down

0 comments on commit 75b190a

Please sign in to comment.