From b955cf278d5ab5043a7d110014f22b32bf95aeb6 Mon Sep 17 00:00:00 2001 From: Joaquim Verges Date: Wed, 15 Oct 2025 22:26:59 +1300 Subject: [PATCH] Fix query cache for block explorers for raw chains --- .changeset/eight-zoos-invent.md | 6 +++ .../extensions/erc721/read/getNFTs.test.ts | 5 ++ .../react/core/hooks/others/useChainQuery.ts | 48 ++++++++----------- .../screens/WalletTransactionHistory.tsx | 16 +++---- .../src/transaction/transaction-store.ts | 11 ++++- 5 files changed, 48 insertions(+), 38 deletions(-) create mode 100644 .changeset/eight-zoos-invent.md diff --git a/.changeset/eight-zoos-invent.md b/.changeset/eight-zoos-invent.md new file mode 100644 index 00000000000..b91ab0d84b8 --- /dev/null +++ b/.changeset/eight-zoos-invent.md @@ -0,0 +1,6 @@ +--- +"thirdweb": patch +--- + +Improve Transactions list in connect modal +Fix query cache for block explorers for raw chains diff --git a/packages/thirdweb/src/extensions/erc721/read/getNFTs.test.ts b/packages/thirdweb/src/extensions/erc721/read/getNFTs.test.ts index 7b55f32d77f..2b823c6d052 100644 --- a/packages/thirdweb/src/extensions/erc721/read/getNFTs.test.ts +++ b/packages/thirdweb/src/extensions/erc721/read/getNFTs.test.ts @@ -41,6 +41,7 @@ describe.runIf(process.env.TW_SECRET_KEY)("erc721.getNFTs", () => { "value": "tan", }, ], + "contract_address": "0x8a90cab2b38dba80c64b7734e58ee1db38b8992e", "description": "A community-driven collectibles project featuring art by Burnt Toast. Doodles come in a joyful range of colors, traits and sizes with a collection size of 10,000. Each Doodle allows its owner to vote for experiences and activations paid for by the Doodles Community Treasury. Burnt Toast is the working alias for Scott Martin, a Canadian–based illustrator, designer, animator and muralist.", "image": "ipfs://QmUEfFfwAh4wyB5UfHCVPUxis4j4Q4kJXtm5x5p3g1fVUn", "image_url": "ipfs://QmUEfFfwAh4wyB5UfHCVPUxis4j4Q4kJXtm5x5p3g1fVUn", @@ -78,6 +79,7 @@ describe.runIf(process.env.TW_SECRET_KEY)("erc721.getNFTs", () => { "value": "gradient 2", }, ], + "contract_address": "0x8a90cab2b38dba80c64b7734e58ee1db38b8992e", "description": "A community-driven collectibles project featuring art by Burnt Toast. Doodles come in a joyful range of colors, traits and sizes with a collection size of 10,000. Each Doodle allows its owner to vote for experiences and activations paid for by the Doodles Community Treasury. Burnt Toast is the working alias for Scott Martin, a Canadian–based illustrator, designer, animator and muralist.", "image": "ipfs://QmTDxnzcvj2p3xBrKcGv1wxoyhAn2yzCQnZZ9LmFjReuH9", "image_url": "ipfs://QmTDxnzcvj2p3xBrKcGv1wxoyhAn2yzCQnZZ9LmFjReuH9", @@ -115,6 +117,7 @@ describe.runIf(process.env.TW_SECRET_KEY)("erc721.getNFTs", () => { "value": "purple", }, ], + "contract_address": "0x8a90cab2b38dba80c64b7734e58ee1db38b8992e", "description": "A community-driven collectibles project featuring art by Burnt Toast. Doodles come in a joyful range of colors, traits and sizes with a collection size of 10,000. Each Doodle allows its owner to vote for experiences and activations paid for by the Doodles Community Treasury. Burnt Toast is the working alias for Scott Martin, a Canadian–based illustrator, designer, animator and muralist.", "image": "ipfs://QmbvZ2hbF3nEq5r3ijMEiSGssAmJvtyFwiejTAGHv74LR5", "image_url": "ipfs://QmbvZ2hbF3nEq5r3ijMEiSGssAmJvtyFwiejTAGHv74LR5", @@ -152,6 +155,7 @@ describe.runIf(process.env.TW_SECRET_KEY)("erc721.getNFTs", () => { "value": "pale", }, ], + "contract_address": "0x8a90cab2b38dba80c64b7734e58ee1db38b8992e", "description": "A community-driven collectibles project featuring art by Burnt Toast. Doodles come in a joyful range of colors, traits and sizes with a collection size of 10,000. Each Doodle allows its owner to vote for experiences and activations paid for by the Doodles Community Treasury. Burnt Toast is the working alias for Scott Martin, a Canadian–based illustrator, designer, animator and muralist.", "image": "ipfs://QmVpwaCqLut3wqwB5KSQr2fGnbLuJt5e3LhNvzvcisewZB", "image_url": "ipfs://QmVpwaCqLut3wqwB5KSQr2fGnbLuJt5e3LhNvzvcisewZB", @@ -189,6 +193,7 @@ describe.runIf(process.env.TW_SECRET_KEY)("erc721.getNFTs", () => { "value": "purple", }, ], + "contract_address": "0x8a90cab2b38dba80c64b7734e58ee1db38b8992e", "description": "A community-driven collectibles project featuring art by Burnt Toast. Doodles come in a joyful range of colors, traits and sizes with a collection size of 10,000. Each Doodle allows its owner to vote for experiences and activations paid for by the Doodles Community Treasury. Burnt Toast is the working alias for Scott Martin, a Canadian–based illustrator, designer, animator and muralist.", "image": "ipfs://QmcyuFVLbfBmSeQ9ynu4dk67r97nB1abEekotuVuRGWedm", "image_url": "ipfs://QmcyuFVLbfBmSeQ9ynu4dk67r97nB1abEekotuVuRGWedm", diff --git a/packages/thirdweb/src/react/core/hooks/others/useChainQuery.ts b/packages/thirdweb/src/react/core/hooks/others/useChainQuery.ts index f5ad66b28f2..70d8c05c928 100644 --- a/packages/thirdweb/src/react/core/hooks/others/useChainQuery.ts +++ b/packages/thirdweb/src/react/core/hooks/others/useChainQuery.ts @@ -15,17 +15,15 @@ export function useChainName(chain?: Chain) { // only if we have a chain and no chain name! const isEnabled = !!chain && !chain.name; const chainQuery = useQuery({ - enabled: isEnabled, queryFn: async () => { if (!chain) { throw new Error("chain is required"); } return convertApiChainToChain(await getChainMetadata(chain)); }, - queryKey: ["chain", chain?.id], + ...getQueryOptions(chain), + enabled: isEnabled, retry: false, - // 1 hour - staleTime: 60 * 60 * 1000, }); return { @@ -39,17 +37,15 @@ export function useChainIconUrl(chain?: Chain) { const isEnabled = !!chain && !chain.icon?.url; const chainQuery = useQuery({ // only if we have a chain and no chain icon url! - enabled: isEnabled, queryFn: async () => { if (!chain) { throw new Error("chain is required"); } return convertApiChainToChain(await getChainMetadata(chain)); }, - queryKey: ["chain", chain?.id], + ...getQueryOptions(chain), + enabled: isEnabled, retry: false, - // 1 hour - staleTime: 60 * 60 * 1000, }); return { @@ -67,17 +63,14 @@ export function useChainFaucets(chain?: Chain) { chain.id !== 1337; const chainQuery = useQuery({ - enabled: isEnabled, queryFn: async () => { if (!chain) { throw new Error("chain is required"); } - return convertApiChainToChain(await getChainMetadata(chain)); + return getChainMetadata(chain); }, - queryKey: ["chain", chain?.id], - retry: false, - // 1 hour - staleTime: 60 * 60 * 1000, + ...getQueryOptions(chain), + enabled: isEnabled, }); return { @@ -90,18 +83,14 @@ export function useChainSymbol(chain?: Chain) { // only if we have a chain and no chain icon url! const isEnabled = !!chain && !chain.nativeCurrency?.symbol; const chainQuery = useQuery({ - // only if we have a chain and no chain icon url! - enabled: isEnabled, queryFn: async () => { if (!chain) { throw new Error("chain is required"); } - return convertApiChainToChain(await getChainMetadata(chain)); + return getChainMetadata(chain); }, - queryKey: ["chain", chain?.id], - retry: false, - // 1 hour - staleTime: 60 * 60 * 1000, + ...getQueryOptions(chain), + enabled: isEnabled, }); return { @@ -116,21 +105,24 @@ export function useChainExplorers(chain?: Chain) { const isEnabled = !!chain && !chain.blockExplorers?.length; const chainQuery = useQuery({ - enabled: isEnabled, queryFn: async () => { if (!chain) { throw new Error("chain is required"); } - return convertApiChainToChain(await getChainMetadata(chain)); + return getChainMetadata(chain); }, - queryKey: ["chain", chain?.id], - retry: false, - // 1 hour - staleTime: 60 * 60 * 1000, + ...getQueryOptions(chain), + enabled: isEnabled, }); + const toChain = chainQuery.data + ? convertApiChainToChain(chainQuery.data) + : undefined; return { - explorers: chain?.blockExplorers ?? chainQuery.data?.blockExplorers ?? [], + explorers: + chain?.blockExplorers && chain?.blockExplorers?.length > 0 + ? chain?.blockExplorers + : (toChain?.blockExplorers ?? []), isLoading: isEnabled && chainQuery.isLoading, }; } diff --git a/packages/thirdweb/src/react/web/ui/ConnectWallet/screens/WalletTransactionHistory.tsx b/packages/thirdweb/src/react/web/ui/ConnectWallet/screens/WalletTransactionHistory.tsx index de3d28ff1c6..f8344727706 100644 --- a/packages/thirdweb/src/react/web/ui/ConnectWallet/screens/WalletTransactionHistory.tsx +++ b/packages/thirdweb/src/react/web/ui/ConnectWallet/screens/WalletTransactionHistory.tsx @@ -24,7 +24,6 @@ import { useActiveWalletChain } from "../../../../core/hooks/wallets/useActiveWa import { Container } from "../../components/basic.js"; import { Button } from "../../components/buttons.js"; import { ChainIcon } from "../../components/ChainIcon.js"; -import { ChainName } from "../../components/ChainName.js"; import { Spacer } from "../../components/Spacer.js"; import { Spinner } from "../../components/Spinner.js"; import { Text } from "../../components/text.js"; @@ -141,6 +140,7 @@ function TransactionButton(props: { }); const chainIconQuery = useChainIconUrl(getCachedChain(props.tx.chainId)); const receipt = props.tx.receipt ?? fetchedReceipt; + const decoded = props.tx.decoded; const content = ( - {receipt?.to - ? `Interacted with ${shortenHex(receipt?.to, 4)}` - : `Hash: ${shortenHex(props.tx.transactionHash, 4)}`} + {decoded ? decoded.name : `Transaction Sent`} @@ -198,11 +196,11 @@ function TransactionButton(props: { justifyContent: "space-between", }} > - + + {receipt?.to + ? shortenHex(receipt?.to, 4) + : shortenHex(props.tx.transactionHash, 4)} + diff --git a/packages/thirdweb/src/transaction/transaction-store.ts b/packages/thirdweb/src/transaction/transaction-store.ts index 970efb8db31..7019d4cd84c 100644 --- a/packages/thirdweb/src/transaction/transaction-store.ts +++ b/packages/thirdweb/src/transaction/transaction-store.ts @@ -11,6 +11,13 @@ export type StoredTransaction = { status: "success" | "failed"; to: string; }; + decoded?: { + name: string; + signature: string; + inputs?: { + [key: string]: unknown; + }; + }; }; const transactionsByAddress = new Map>(); @@ -81,6 +88,7 @@ export async function getPastTransactions(options: { queryOptions: { filter_block_timestamp_gte: oneMonthsAgoInSeconds, limit: 20, + decode: true, }, walletAddress, }); @@ -90,9 +98,10 @@ export async function getPastTransactions(options: { ? Number(tx.chain_id) : (tx.chain_id as number), receipt: { - status: tx.status === 1 ? "success" : "failed", + status: tx.status === 0 ? "failed" : "success", to: tx.to_address, }, transactionHash: tx.hash as Hex, + decoded: tx.decoded, })); }