Skip to content

Commit 2bf4b91

Browse files
cleanup
1 parent 79f10bb commit 2bf4b91

File tree

2 files changed

+809
-807
lines changed

2 files changed

+809
-807
lines changed

apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/tx/[id]/page.tsx

Lines changed: 172 additions & 168 deletions
Original file line numberDiff line numberDiff line change
@@ -11,193 +11,197 @@ import { getClientThirdwebClient } from "@/constants/thirdweb-client.client";
1111
import { serverThirdwebClient } from "@/constants/thirdweb-client.server";
1212
import type { Transaction } from "../../analytics/tx-table/types";
1313
import {
14-
getSingleTransaction,
15-
getTransactionActivityLogs,
14+
getSingleTransaction,
15+
getTransactionActivityLogs,
1616
} from "../../lib/analytics";
1717
import { TransactionDetailsUI } from "./transaction-details-ui";
1818

1919
type AbiItem =
20-
| AbiFunction
21-
| {
22-
type: string;
23-
name?: string;
24-
};
20+
| AbiFunction
21+
| {
22+
type: string;
23+
name?: string;
24+
};
2525

2626
export type DecodedTransactionData = {
27-
contractName: string;
28-
functionName: string;
29-
functionArgs: Record<string, unknown>;
27+
contractName: string;
28+
functionName: string;
29+
functionArgs: Record<string, unknown>;
3030
} | null;
3131

3232
export type DecodedTransactionResult = DecodedTransactionData[];
3333

3434
async function decodeSingleTransactionParam(
35-
txParam: any,
36-
chainId: number,
35+
txParam: {
36+
to: string;
37+
data: `0x${string}`;
38+
},
39+
chainId: number,
3740
): Promise<DecodedTransactionData> {
38-
try {
39-
if (!txParam || !txParam.to || !txParam.data) {
40-
return null;
41-
}
42-
43-
// Create contract instance
44-
const contract = getContract({
45-
client: serverThirdwebClient,
46-
address: txParam.to,
47-
chain: defineChain(chainId),
48-
});
49-
50-
// Fetch compiler metadata
51-
const compilerMetadata = await getCompilerMetadata(contract);
52-
53-
if (!compilerMetadata || !compilerMetadata.abi) {
54-
return null;
55-
}
56-
57-
const contractName = compilerMetadata.name || "Unknown Contract";
58-
const abi = compilerMetadata.abi;
59-
60-
// Extract function selector from transaction data (first 4 bytes)
61-
const functionSelector = txParam.data.slice(0, 10) as `0x${string}`;
62-
63-
// Find matching function in ABI
64-
const functions = (abi as readonly AbiItem[]).filter(
65-
(item): item is AbiFunction => item.type === "function",
66-
);
67-
let matchingFunction: AbiFunction | null = null;
68-
69-
for (const func of functions) {
70-
const selector = toFunctionSelector(func);
71-
if (selector === functionSelector) {
72-
matchingFunction = func;
73-
break;
74-
}
75-
}
76-
77-
if (!matchingFunction) {
78-
return null;
79-
}
80-
81-
const functionName = matchingFunction.name;
82-
83-
// Decode function data
84-
const decodedArgs = (await decodeFunctionData({
85-
contract: getContract({
86-
...contract,
87-
abi: [matchingFunction],
88-
}),
89-
data: txParam.data,
90-
})) as readonly unknown[];
91-
92-
// Create a clean object for display
93-
const functionArgs: Record<string, unknown> = {};
94-
if (matchingFunction.inputs && decodedArgs) {
95-
for (let index = 0; index < matchingFunction.inputs.length; index++) {
96-
const input = matchingFunction.inputs[index];
97-
if (input) {
98-
functionArgs[input.name || `arg${index}`] = decodedArgs[index];
99-
}
100-
}
101-
}
102-
103-
return {
104-
contractName,
105-
functionName,
106-
functionArgs,
107-
};
108-
} catch (error) {
109-
console.error("Error decoding transaction param:", error);
110-
return null;
111-
}
41+
try {
42+
if (!txParam || !txParam.to || !txParam.data) {
43+
return null;
44+
}
45+
46+
// Create contract instance
47+
const contract = getContract({
48+
address: txParam.to,
49+
// eslint-disable-next-line no-restricted-syntax
50+
chain: defineChain(chainId),
51+
client: serverThirdwebClient,
52+
});
53+
54+
// Fetch compiler metadata
55+
const compilerMetadata = await getCompilerMetadata(contract);
56+
57+
if (!compilerMetadata || !compilerMetadata.abi) {
58+
return null;
59+
}
60+
61+
const contractName = compilerMetadata.name || "Unknown Contract";
62+
const abi = compilerMetadata.abi;
63+
64+
// Extract function selector from transaction data (first 4 bytes)
65+
const functionSelector = txParam.data.slice(0, 10) as `0x${string}`;
66+
67+
// Find matching function in ABI
68+
const functions = (abi as readonly AbiItem[]).filter(
69+
(item): item is AbiFunction => item.type === "function",
70+
);
71+
let matchingFunction: AbiFunction | null = null;
72+
73+
for (const func of functions) {
74+
const selector = toFunctionSelector(func);
75+
if (selector === functionSelector) {
76+
matchingFunction = func;
77+
break;
78+
}
79+
}
80+
81+
if (!matchingFunction) {
82+
return null;
83+
}
84+
85+
const functionName = matchingFunction.name;
86+
87+
// Decode function data
88+
const decodedArgs = (await decodeFunctionData({
89+
contract: getContract({
90+
...contract,
91+
abi: [matchingFunction],
92+
}),
93+
data: txParam.data,
94+
})) as readonly unknown[];
95+
96+
// Create a clean object for display
97+
const functionArgs: Record<string, unknown> = {};
98+
if (matchingFunction.inputs && decodedArgs) {
99+
for (let index = 0; index < matchingFunction.inputs.length; index++) {
100+
const input = matchingFunction.inputs[index];
101+
if (input) {
102+
functionArgs[input.name || `arg${index}`] = decodedArgs[index];
103+
}
104+
}
105+
}
106+
107+
return {
108+
contractName,
109+
functionArgs,
110+
functionName,
111+
};
112+
} catch (error) {
113+
console.error("Error decoding transaction param:", error);
114+
return null;
115+
}
112116
}
113117

114118
async function decodeTransactionData(
115-
transaction: Transaction,
119+
transaction: Transaction,
116120
): Promise<DecodedTransactionResult> {
117-
try {
118-
// Check if we have transaction parameters
119-
if (
120-
!transaction.transactionParams ||
121-
transaction.transactionParams.length === 0
122-
) {
123-
return [];
124-
}
125-
126-
// Ensure we have a chainId
127-
if (!transaction.chainId) {
128-
return [];
129-
}
130-
131-
const chainId = parseInt(transaction.chainId);
132-
133-
// Decode all transaction parameters in parallel
134-
const decodingPromises = transaction.transactionParams.map((txParam) =>
135-
decodeSingleTransactionParam(txParam, chainId),
136-
);
137-
138-
const results = await Promise.all(decodingPromises);
139-
return results;
140-
} catch (error) {
141-
console.error("Error decoding transaction:", error);
142-
return [];
143-
}
121+
try {
122+
// Check if we have transaction parameters
123+
if (
124+
!transaction.transactionParams ||
125+
transaction.transactionParams.length === 0
126+
) {
127+
return [];
128+
}
129+
130+
// Ensure we have a chainId
131+
if (!transaction.chainId) {
132+
return [];
133+
}
134+
135+
const chainId = parseInt(transaction.chainId);
136+
137+
// Decode all transaction parameters in parallel
138+
const decodingPromises = transaction.transactionParams.map((txParam) =>
139+
decodeSingleTransactionParam(txParam, chainId),
140+
);
141+
142+
const results = await Promise.all(decodingPromises);
143+
return results;
144+
} catch (error) {
145+
console.error("Error decoding transaction:", error);
146+
return [];
147+
}
144148
}
145149

146150
export default async function TransactionPage({
147-
params,
151+
params,
148152
}: {
149-
params: Promise<{ team_slug: string; project_slug: string; id: string }>;
153+
params: Promise<{ team_slug: string; project_slug: string; id: string }>;
150154
}) {
151-
const { team_slug, project_slug, id } = await params;
152-
153-
const [authToken, project] = await Promise.all([
154-
getAuthToken(),
155-
getProject(team_slug, project_slug),
156-
]);
157-
158-
if (!authToken) {
159-
loginRedirect(`/team/${team_slug}/${project_slug}/transactions/tx/${id}`);
160-
}
161-
162-
if (!project) {
163-
redirect(`/team/${team_slug}`);
164-
}
165-
166-
const [transactionData, activityLogs] = await Promise.all([
167-
getSingleTransaction({
168-
clientId: project.publishableKey,
169-
teamId: project.teamId,
170-
transactionId: id,
171-
}),
172-
getTransactionActivityLogs({
173-
clientId: project.publishableKey,
174-
teamId: project.teamId,
175-
transactionId: id,
176-
}),
177-
]);
178-
179-
const client = getClientThirdwebClient({
180-
jwt: authToken,
181-
teamId: project.teamId,
182-
});
183-
184-
if (!transactionData) {
185-
notFound();
186-
}
187-
188-
// Decode transaction data on the server
189-
const decodedTransactionData = await decodeTransactionData(transactionData);
190-
191-
return (
192-
<div className="space-y-6 p-2">
193-
<TransactionDetailsUI
194-
activityLogs={activityLogs}
195-
client={client}
196-
project={project}
197-
teamSlug={team_slug}
198-
transaction={transactionData}
199-
decodedTransactionData={decodedTransactionData}
200-
/>
201-
</div>
202-
);
155+
const { team_slug, project_slug, id } = await params;
156+
157+
const [authToken, project] = await Promise.all([
158+
getAuthToken(),
159+
getProject(team_slug, project_slug),
160+
]);
161+
162+
if (!authToken) {
163+
loginRedirect(`/team/${team_slug}/${project_slug}/transactions/tx/${id}`);
164+
}
165+
166+
if (!project) {
167+
redirect(`/team/${team_slug}`);
168+
}
169+
170+
const [transactionData, activityLogs] = await Promise.all([
171+
getSingleTransaction({
172+
clientId: project.publishableKey,
173+
teamId: project.teamId,
174+
transactionId: id,
175+
}),
176+
getTransactionActivityLogs({
177+
clientId: project.publishableKey,
178+
teamId: project.teamId,
179+
transactionId: id,
180+
}),
181+
]);
182+
183+
const client = getClientThirdwebClient({
184+
jwt: authToken,
185+
teamId: project.teamId,
186+
});
187+
188+
if (!transactionData) {
189+
notFound();
190+
}
191+
192+
// Decode transaction data on the server
193+
const decodedTransactionData = await decodeTransactionData(transactionData);
194+
195+
return (
196+
<div className="space-y-6 p-2">
197+
<TransactionDetailsUI
198+
activityLogs={activityLogs}
199+
client={client}
200+
decodedTransactionData={decodedTransactionData}
201+
project={project}
202+
teamSlug={team_slug}
203+
transaction={transactionData}
204+
/>
205+
</div>
206+
);
203207
}

0 commit comments

Comments
 (0)