@b3dotfun/sdk 0.0.9-alpha.8 → 0.0.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -8,6 +8,7 @@ export declare const SOLANA_ASSOCIATED_TOKEN_ACCOUNT_PROGRAM_ID = "ATokenGPvbdGV
8
8
  export declare const SOLANA_TOKEN_2022_PROGRAM_ID = "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb";
9
9
  export declare const B3_TOKEN: components["schemas"]["Token"];
10
10
  export declare const USDC_BASE: components["schemas"]["Token"];
11
+ export declare const ETH_BASE: components["schemas"]["Token"];
11
12
  export declare const NFT_CONTRACTS: components["schemas"]["NftContract"][];
12
13
  export declare const DEFAULT_NFT_CONTRACT: {
13
14
  chainId: number;
@@ -15,7 +16,7 @@ export declare const DEFAULT_NFT_CONTRACT: {
15
16
  price: string;
16
17
  priceFormatted: string;
17
18
  currency: components["schemas"]["Token"];
18
- imageUrl: string;
19
+ imageUrl: string | null;
19
20
  name: string;
20
21
  description: string;
21
22
  tokenId: number | null;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.VENDOR_DISPLAY_NAMES = exports.PAYMENT_METHOD_ICONS = exports.STRIPE_CONFIG = exports.DEFAULT_NFT_CONTRACT = exports.NFT_CONTRACTS = exports.USDC_BASE = exports.B3_TOKEN = exports.SOLANA_TOKEN_2022_PROGRAM_ID = exports.SOLANA_ASSOCIATED_TOKEN_ACCOUNT_PROGRAM_ID = exports.RELAY_SOLANA_MAINNET_CHAIN_ID = exports.RELAY_SOL_ADDRESS = exports.RELAY_ETH_ADDRESS = exports.ANYSPEND_TESTNET_BASE_URL = exports.ANYSPEND_MAINNET_BASE_URL = void 0;
3
+ exports.VENDOR_DISPLAY_NAMES = exports.PAYMENT_METHOD_ICONS = exports.STRIPE_CONFIG = exports.DEFAULT_NFT_CONTRACT = exports.NFT_CONTRACTS = exports.ETH_BASE = exports.USDC_BASE = exports.B3_TOKEN = exports.SOLANA_TOKEN_2022_PROGRAM_ID = exports.SOLANA_ASSOCIATED_TOKEN_ACCOUNT_PROGRAM_ID = exports.RELAY_SOLANA_MAINNET_CHAIN_ID = exports.RELAY_SOL_ADDRESS = exports.RELAY_ETH_ADDRESS = exports.ANYSPEND_TESTNET_BASE_URL = exports.ANYSPEND_MAINNET_BASE_URL = void 0;
4
4
  const chains_1 = require("viem/chains");
5
5
  exports.ANYSPEND_MAINNET_BASE_URL = process.env.NEXT_PUBLIC_ANYSPEND_BASE_URL || "https://mainnet.anyspend.com";
6
6
  exports.ANYSPEND_TESTNET_BASE_URL = process.env.NEXT_PUBLIC_ANYSPEND_BASE_URL || "https://testnet.anyspend.com";
@@ -29,6 +29,16 @@ exports.USDC_BASE = {
29
29
  logoURI: "https://polygonscan.com/token/images/usdc_32.png",
30
30
  },
31
31
  };
32
+ exports.ETH_BASE = {
33
+ symbol: "ETH",
34
+ chainId: chains_1.base.id,
35
+ address: "0x0000000000000000000000000000000000000000",
36
+ name: "Ethereum",
37
+ decimals: 18,
38
+ metadata: {
39
+ logoURI: "https://polygonscan.com/token/images/eth_32.png",
40
+ },
41
+ };
32
42
  exports.NFT_CONTRACTS = [
33
43
  {
34
44
  chainId: chains_1.base.id,
@@ -12,8 +12,78 @@ const lucide_react_1 = require("lucide-react");
12
12
  const react_2 = require("react");
13
13
  const chains_1 = require("viem/chains");
14
14
  const AnySpendCustom_1 = require("./AnySpendCustom");
15
+ // ABI for contractURI and uri functions
16
+ const CONTRACT_URI_ABI = [
17
+ {
18
+ inputs: [],
19
+ name: "contractURI",
20
+ outputs: [{ internalType: "string", name: "", type: "string" }],
21
+ stateMutability: "view",
22
+ type: "function",
23
+ },
24
+ {
25
+ inputs: [{ internalType: "uint256", name: "_tokenId", type: "uint256" }],
26
+ name: "uri",
27
+ outputs: [{ internalType: "string", name: "", type: "string" }],
28
+ stateMutability: "view",
29
+ type: "function",
30
+ },
31
+ ];
15
32
  function AnySpendNFT({ isMainnet = true, loadOrder, mode = "modal", recipientAddress, nftContract, onSuccess, }) {
16
- const header = ({ anyspendPrice, isLoadingAnyspendPrice, }) => ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsxs)("div", { className: "relative size-[200px]", children: [(0, jsx_runtime_1.jsx)("div", { className: "absolute inset-0 scale-95 bg-black/30 blur-md" }), (0, jsx_runtime_1.jsxs)(react_1.GlareCard, { className: "overflow-hidden", children: [(0, jsx_runtime_1.jsx)("img", { src: (0, ipfs_1.getIpfsUrl)(nftContract.imageUrl), alt: nftContract.name, className: "size-full object-cover" }), (0, jsx_runtime_1.jsx)("div", { className: "absolute inset-0 rounded-xl border border-white/10" })] }), (0, jsx_runtime_1.jsx)(DropdownMenu, { nftContract: nftContract })] }), (0, jsx_runtime_1.jsxs)("div", { className: "from-b3-react-background to-as-on-surface-1 mt-[-100px] w-full rounded-t-lg bg-gradient-to-t", children: [(0, jsx_runtime_1.jsx)("div", { className: "h-[100px] w-full" }), (0, jsx_runtime_1.jsxs)("div", { className: "mb-1 flex w-full flex-col items-center gap-2 p-5", children: [(0, jsx_runtime_1.jsx)("span", { className: "font-sf-rounded text-2xl font-semibold", children: nftContract.name }), (0, jsx_runtime_1.jsx)("div", { className: "flex w-fit items-center gap-1", children: anyspendPrice ? ((0, jsx_runtime_1.jsx)(framer_motion_1.AnimatePresence, { mode: "wait", children: (0, jsx_runtime_1.jsx)("div", { className: (0, utils_1.cn)("text-as-primary group flex items-center text-3xl font-semibold transition-all", {
33
+ const [imageUrlWithFallback, setFallbackImageUrl] = (0, react_2.useState)(nftContract.imageUrl);
34
+ const [isLoadingFallback, setIsLoadingFallback] = (0, react_2.useState)(false);
35
+ // Fetch contract metadata when imageUrl is empty
36
+ (0, react_2.useEffect)(() => {
37
+ async function fetchContractMetadata() {
38
+ // fetch image Uri if not provided
39
+ if (nftContract.imageUrl || isLoadingFallback) {
40
+ return;
41
+ }
42
+ try {
43
+ setIsLoadingFallback(true);
44
+ // Use the chainIdToPublicClient utility function
45
+ const publicClient = (0, anyspend_1.chainIdToPublicClient)(nftContract.chainId);
46
+ let metadataURI;
47
+ // Use uri function if tokenId is available, otherwise use contractURI
48
+ if (nftContract.tokenId !== null && nftContract.tokenId !== undefined) {
49
+ console.log("Using uri function with tokenId:", nftContract.tokenId);
50
+ metadataURI = await publicClient.readContract({
51
+ address: nftContract.contractAddress,
52
+ abi: CONTRACT_URI_ABI,
53
+ functionName: "uri",
54
+ args: [BigInt(nftContract.tokenId)],
55
+ });
56
+ }
57
+ else {
58
+ console.log("Using contractURI function");
59
+ metadataURI = await publicClient.readContract({
60
+ address: nftContract.contractAddress,
61
+ abi: CONTRACT_URI_ABI,
62
+ functionName: "contractURI",
63
+ });
64
+ }
65
+ if (metadataURI) {
66
+ // Fetch the metadata from IPFS
67
+ const metadataUrl = (0, ipfs_1.getIpfsUrl)(metadataURI);
68
+ const response = await fetch(metadataUrl);
69
+ const metadata = await response.json();
70
+ if (metadata.image) {
71
+ const fallbackUrl = (0, ipfs_1.getIpfsUrl)(metadata.image);
72
+ setFallbackImageUrl(fallbackUrl);
73
+ console.log("fallbackImageUrl", fallbackUrl);
74
+ }
75
+ }
76
+ }
77
+ catch (error) {
78
+ console.error("Error fetching contract metadata:", error);
79
+ }
80
+ finally {
81
+ setIsLoadingFallback(false);
82
+ }
83
+ }
84
+ fetchContractMetadata();
85
+ }, [nftContract.contractAddress, nftContract.chainId, nftContract.imageUrl, nftContract.tokenId]);
86
+ const header = ({ anyspendPrice, isLoadingAnyspendPrice, }) => ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsxs)("div", { className: "relative size-[200px]", children: [(0, jsx_runtime_1.jsx)("div", { className: "absolute inset-0 scale-95 bg-black/30 blur-md" }), (0, jsx_runtime_1.jsxs)(react_1.GlareCard, { className: "overflow-hidden", children: [imageUrlWithFallback && ((0, jsx_runtime_1.jsx)("img", { src: imageUrlWithFallback, alt: nftContract.name, className: "size-full object-cover" })), (0, jsx_runtime_1.jsx)("div", { className: "absolute inset-0 rounded-xl border border-white/10" })] }), (0, jsx_runtime_1.jsx)(DropdownMenu, { nftContract: nftContract })] }), (0, jsx_runtime_1.jsxs)("div", { className: "from-b3-react-background to-as-on-surface-1 mt-[-100px] w-full rounded-t-lg bg-gradient-to-t", children: [(0, jsx_runtime_1.jsx)("div", { className: "h-[100px] w-full" }), (0, jsx_runtime_1.jsxs)("div", { className: "mb-1 flex w-full flex-col items-center gap-2 p-5", children: [(0, jsx_runtime_1.jsx)("span", { className: "font-sf-rounded text-2xl font-semibold", children: nftContract.name }), (0, jsx_runtime_1.jsx)("div", { className: "flex w-fit items-center gap-1", children: anyspendPrice ? ((0, jsx_runtime_1.jsx)(framer_motion_1.AnimatePresence, { mode: "wait", children: (0, jsx_runtime_1.jsx)("div", { className: (0, utils_1.cn)("text-as-primary group flex items-center text-3xl font-semibold transition-all", {
17
87
  "opacity-0": isLoadingAnyspendPrice,
18
88
  }), children: (0, number_1.formatDisplayNumber)(anyspendPrice?.data?.currencyIn?.amountUsd, { style: "currency" }) }) })) : ((0, jsx_runtime_1.jsx)("div", { className: "h-[36px] w-full" })) })] })] })] }));
19
89
  return ((0, jsx_runtime_1.jsx)(AnySpendCustom_1.AnySpendCustom, { isMainnet: isMainnet, loadOrder: loadOrder, mode: mode, recipientAddress: recipientAddress, orderType: "mint_nft", dstChainId: nftContract.chainId, dstToken: nftContract.currency, dstAmount: nftContract.price, contractAddress: nftContract.contractAddress, encodedData: "0x", metadata: {
@@ -475,7 +475,9 @@ exports.OrderDetails = (0, react_4.memo)(function OrderDetails({ isMainnet, mode
475
475
  sonner_1.toast.success("Copied to clipboard");
476
476
  }, children: (0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-2", children: [(0, jsx_runtime_1.jsxs)("strong", { className: "border-as-brand text-as-primary border-b-2 pb-1 text-2xl font-semibold sm:text-xl", children: [roundedUpSrcAmount, " ", srcToken.symbol] }), (0, jsx_runtime_1.jsx)(lucide_react_1.Copy, { className: "text-as-primary/50 hover:text-as-primary h-5 w-5 cursor-pointer transition-all duration-200" })] }) }), (0, jsx_runtime_1.jsxs)(react_1.Badge, { variant: "outline", className: "flex h-10 items-center gap-2 px-3 py-1 pr-2 text-sm", children: ["on ", (0, anyspend_1.getChainName)(order.srcChain), (0, jsx_runtime_1.jsx)("img", { src: anyspend_1.ALL_CHAINS[order.srcChain].logoUrl, alt: (0, anyspend_1.getChainName)(order.srcChain), className: (0, utils_1.cn)("h-6 rounded-full", order.srcChain === chains_1.b3.id && "h-5 rounded-none") })] })] }), (0, jsx_runtime_1.jsx)("span", { className: "text-as-primary/50 mb-1 mt-2", children: " to the address:" })] }), (0, jsx_runtime_1.jsx)(react_1.CopyToClipboard, { text: order.globalAddress, onCopy: () => {
477
477
  sonner_1.toast.success("Copied to clipboard");
478
- }, children: (0, jsx_runtime_1.jsxs)("div", { className: "bg-b3-react-background border-b3-react-border hover:border-as-brand group flex cursor-pointer items-center justify-between gap-4 rounded-lg border p-3 px-4 shadow-md transition-all duration-200", children: [(0, jsx_runtime_1.jsx)("div", { className: "text-as-primary overflow-hidden text-ellipsis whitespace-nowrap text-sm", children: order.globalAddress }), (0, jsx_runtime_1.jsx)(lucide_react_1.Copy, { className: "group-hover:text-as-brand text-as-primary/50 h-5 w-5 cursor-pointer transition-all duration-200" })] }) }), (account?.address || phantomWalletAddress) && !showQRCode ? ((0, jsx_runtime_1.jsxs)("div", { className: "mb-4 mt-8 flex w-full flex-col items-center gap-4", children: [(0, jsx_runtime_1.jsxs)("div", { className: "relative flex w-full flex-col items-center gap-2", children: [(0, jsx_runtime_1.jsx)(react_1.ShinyButton, { accentColor: "hsl(var(--as-brand))", textColor: "text-white", className: "flex w-5/6 items-center gap-2 sm:px-0", disabled: txLoading || isSwitchingOrExecuting, onClick: handlePayment, children: txLoading ? ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: ["Transaction Pending", (0, jsx_runtime_1.jsx)(lucide_react_1.Loader2, { className: "ml-2 h-5 w-5 animate-spin" })] })) : ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("span", { className: "pl-4 text-lg md:text-sm", children: "Pay from Connected Wallet" }), (0, jsx_runtime_1.jsx)(lucide_react_1.ChevronRight, { className: "h-4 w-4" })] })) }), (0, jsx_runtime_1.jsxs)("span", { className: "label-style text-as-primary/50 text-xs", children: ["Connected to:", " ", order.srcChain === anyspend_1.RELAY_SOLANA_MAINNET_CHAIN_ID && phantomWalletAddress
478
+ }, children: (0, jsx_runtime_1.jsxs)("div", { className: "bg-b3-react-background border-b3-react-border hover:border-as-brand group flex cursor-pointer items-center justify-between gap-4 rounded-lg border p-3 px-4 shadow-md transition-all duration-200", children: [(0, jsx_runtime_1.jsx)("div", { className: "text-as-primary overflow-hidden text-ellipsis whitespace-nowrap text-sm", children: order.globalAddress }), (0, jsx_runtime_1.jsx)(lucide_react_1.Copy, { className: "group-hover:text-as-brand text-as-primary/50 h-5 w-5 cursor-pointer transition-all duration-200" })] }) }), (account?.address || phantomWalletAddress) && !showQRCode ? ((0, jsx_runtime_1.jsxs)("div", { className: "mb-4 mt-8 flex w-full flex-col items-center gap-4", children: [(0, jsx_runtime_1.jsxs)("div", { className: "relative flex w-full flex-col items-center gap-2", children: [(0, jsx_runtime_1.jsx)(react_1.ShinyButton, { accentColor: "hsl(var(--as-brand))", textColor: "text-white", className: "flex w-5/6 items-center gap-2 sm:px-0", disabled: txLoading || isSwitchingOrExecuting, onClick: handlePayment, children: txLoading ? ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: ["Transaction Pending", (0, jsx_runtime_1.jsx)(lucide_react_1.Loader2, { className: "ml-2 h-5 w-5 animate-spin" })] })) : ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("span", { className: "pl-4 text-lg md:text-sm", children: order.srcChain === anyspend_1.RELAY_SOLANA_MAINNET_CHAIN_ID && phantomWalletAddress
479
+ ? "Pay from Phantom Wallet"
480
+ : "Pay from Connected Wallet" }), (0, jsx_runtime_1.jsx)(lucide_react_1.ChevronRight, { className: "h-4 w-4" })] })) }), (0, jsx_runtime_1.jsxs)("span", { className: "label-style text-as-primary/50 text-xs", children: ["Connected to:", " ", order.srcChain === anyspend_1.RELAY_SOLANA_MAINNET_CHAIN_ID && phantomWalletAddress
479
481
  ? (0, centerTruncate_1.default)(phantomWalletAddress, 6)
480
482
  : (0, centerTruncate_1.default)(account?.address || "", 6)] })] }), (0, jsx_runtime_1.jsxs)("div", { className: "flex w-full flex-col items-center gap-2", children: [(0, jsx_runtime_1.jsxs)(react_1.ShinyButton, { accentColor: colorMode === "dark" ? "#ffffff" : "#000000", className: "flex w-5/6 items-center gap-2 sm:px-0", onClick: () => setShowQRCode(true), children: [(0, jsx_runtime_1.jsx)("span", { className: "pl-4 text-lg md:text-sm", children: "Pay from a different wallet" }), (0, jsx_runtime_1.jsx)(lucide_react_1.ChevronRight, { className: "h-4 w-4" })] }), (0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-2", children: [(0, jsx_runtime_1.jsx)(react_3.WalletMetamask, { className: "h-5 w-5", variant: "branded" }), (0, jsx_runtime_1.jsx)(react_3.WalletCoinbase, { className: "h-5 w-5", variant: "branded" }), (0, jsx_runtime_1.jsx)(react_3.WalletPhantom, { className: "h-5 w-5", variant: "branded" }), (0, jsx_runtime_1.jsx)(react_3.WalletTrust, { className: "h-5 w-5", variant: "branded" }), (0, jsx_runtime_1.jsx)(react_3.WalletWalletConnect, { className: "h-5 w-5", variant: "branded" }), (0, jsx_runtime_1.jsx)("span", { className: "label-style text-as-primary/30 text-xs", children: "& more" })] })] })] })) : ((0, jsx_runtime_1.jsxs)(framer_motion_1.motion.div, { initial: { opacity: 0, filter: "blur(10px)" }, animate: { opacity: 1, filter: "blur(0px)" }, transition: { duration: 0.5, ease: "easeInOut" }, className: "flex w-full items-center justify-evenly gap-4", children: [(0, jsx_runtime_1.jsxs)("div", { className: "mt-8 flex flex-col items-center rounded-lg bg-white p-6 pb-3", children: [(0, jsx_runtime_1.jsx)(qrcode_react_1.QRCodeSVG, { value: (0, anyspend_1.getPaymentUrl)(order.globalAddress, BigInt(order.srcAmount), order.srcTokenAddress === anyspend_1.RELAY_ETH_ADDRESS ? "ETH" : order.srcTokenAddress), className: "max-w-[200px]" }), (0, jsx_runtime_1.jsxs)("div", { className: "mt-3 flex items-center justify-center gap-2 text-sm", children: [(0, jsx_runtime_1.jsx)("span", { className: "label-style text-as-brand/70 text-sm", children: "Scan with" }), (0, jsx_runtime_1.jsxs)(react_1.TextLoop, { interval: 3, children: [(0, jsx_runtime_1.jsx)(react_3.WalletMetamask, { className: "h-5 w-5", variant: "branded" }), (0, jsx_runtime_1.jsx)(react_3.WalletCoinbase, { className: "h-5 w-5", variant: "branded" }), (0, jsx_runtime_1.jsx)(react_3.WalletPhantom, { className: "h-5 w-5", variant: "branded" }), (0, jsx_runtime_1.jsx)(react_3.WalletTrust, { className: "h-5 w-5", variant: "branded" }), (0, jsx_runtime_1.jsx)(react_3.WalletWalletConnect, { className: "h-5 w-5", variant: "branded" })] })] })] }), (0, jsx_runtime_1.jsxs)("div", { className: "flex flex-col gap-2", children: [account && ((0, jsx_runtime_1.jsxs)(react_1.Button, { variant: "ghost", className: "text-as-primary w-full", onClick: handlePayment, children: ["Send Transaction ", (0, jsx_runtime_1.jsx)(lucide_react_1.ChevronRight, { className: "ml-2 h-4 w-4" })] })), anyspend_1.EVM_CHAINS[order.srcChain] ? ((0, jsx_runtime_1.jsxs)(react_1.Button, { variant: "outline", className: "w-full", onClick: handlePayment, children: ["Open Metamask", (0, jsx_runtime_1.jsx)(react_3.WalletMetamask, { className: "ml-2 h-5 w-5", variant: "branded" })] })) : null, (0, jsx_runtime_1.jsx)("a", { href: handleCoinbaseRedirect(), children: (0, jsx_runtime_1.jsxs)(react_1.Button, { variant: "outline", className: "w-full", children: ["Open Coinbase", (0, jsx_runtime_1.jsx)(react_3.WalletCoinbase, { className: "ml-2 h-5 w-5", variant: "branded" })] }) }), (0, jsx_runtime_1.jsxs)(react_1.Button, { variant: "outline", className: "w-full", onClick: () => initiatePhantomTransfer(order.srcAmount, order.srcTokenAddress, order.globalAddress), children: ["Open Phantom", (0, jsx_runtime_1.jsx)(react_3.WalletPhantom, { className: "ml-2 h-5 w-5", variant: "branded" })] })] })] }))] })), (0, jsx_runtime_1.jsxs)("div", { className: "bg-as-light-brand/30 w-full rounded-lg p-4 sm:p-2 sm:px-4", children: [(0, jsx_runtime_1.jsx)("p", { className: "text-as-secondary mb-3 text-sm", children: "Continue on another device?" }), (0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-4", children: [(0, jsx_runtime_1.jsx)(react_1.CopyToClipboard, { text: permalink, onCopy: () => {
481
483
  sonner_1.toast.success("Copied to clipboard");
@@ -1673,7 +1673,7 @@ export interface components {
1673
1673
  * @description NFT image URL
1674
1674
  * @example https://example.com/nft.png
1675
1675
  */
1676
- imageUrl: string;
1676
+ imageUrl: string | null;
1677
1677
  /**
1678
1678
  * @description NFT name
1679
1679
  * @example Cool NFT Collection
@@ -900,7 +900,7 @@ const getV1NftsByContractAddress = (options) => {
900
900
  type: 'apiKey'
901
901
  }
902
902
  ],
903
- url: 'https://insight.thirdweb.com/v1/nfts/{contract_address}',
903
+ url: '/v1/nfts/{contract_address}',
904
904
  ...options
905
905
  });
906
906
  };
@@ -5,7 +5,7 @@ const client_gen_1 = require("./generated/client.gen");
5
5
  (function () {
6
6
  // Set BASE URL
7
7
  client_gen_1.client.setConfig({
8
- baseUrl: "https://insight.thirdweb.com",
8
+ baseUrl: "https://8333.insight.thirdweb.com",
9
9
  });
10
10
  // Interceptors for issues described here https://npc-labs.slack.com/archives/C070E6HNG85/p1742446793549779?thread_ts=1741637902.666019&cid=C070E6HNG85
11
11
  client_gen_1.client.interceptors.request.use((request, options) => {
@@ -8,6 +8,7 @@ export declare const SOLANA_ASSOCIATED_TOKEN_ACCOUNT_PROGRAM_ID = "ATokenGPvbdGV
8
8
  export declare const SOLANA_TOKEN_2022_PROGRAM_ID = "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb";
9
9
  export declare const B3_TOKEN: components["schemas"]["Token"];
10
10
  export declare const USDC_BASE: components["schemas"]["Token"];
11
+ export declare const ETH_BASE: components["schemas"]["Token"];
11
12
  export declare const NFT_CONTRACTS: components["schemas"]["NftContract"][];
12
13
  export declare const DEFAULT_NFT_CONTRACT: {
13
14
  chainId: number;
@@ -15,7 +16,7 @@ export declare const DEFAULT_NFT_CONTRACT: {
15
16
  price: string;
16
17
  priceFormatted: string;
17
18
  currency: components["schemas"]["Token"];
18
- imageUrl: string;
19
+ imageUrl: string | null;
19
20
  name: string;
20
21
  description: string;
21
22
  tokenId: number | null;
@@ -26,6 +26,16 @@ export const USDC_BASE = {
26
26
  logoURI: "https://polygonscan.com/token/images/usdc_32.png",
27
27
  },
28
28
  };
29
+ export const ETH_BASE = {
30
+ symbol: "ETH",
31
+ chainId: base.id,
32
+ address: "0x0000000000000000000000000000000000000000",
33
+ name: "Ethereum",
34
+ decimals: 18,
35
+ metadata: {
36
+ logoURI: "https://polygonscan.com/token/images/eth_32.png",
37
+ },
38
+ };
29
39
  export const NFT_CONTRACTS = [
30
40
  {
31
41
  chainId: base.id,
@@ -1,16 +1,86 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
- import { ALL_CHAINS, getChainName, getExplorerAddressUrl } from "../../../anyspend/index.js";
2
+ import { ALL_CHAINS, chainIdToPublicClient, getChainName, getExplorerAddressUrl } from "../../../anyspend/index.js";
3
3
  import { GlareCard, Popover, PopoverContent, PopoverTrigger } from "../../../global-account/react/index.js";
4
4
  import { cn } from "../../../shared/utils/index.js";
5
5
  import { getIpfsUrl } from "../../../shared/utils/ipfs.js";
6
6
  import { formatDisplayNumber, formatTokenAmount } from "../../../shared/utils/number.js";
7
7
  import { AnimatePresence } from "framer-motion";
8
8
  import { MoreVertical } from "lucide-react";
9
- import { useState } from "react";
9
+ import { useEffect, useState } from "react";
10
10
  import { b3 } from "viem/chains";
11
11
  import { AnySpendCustom } from "./AnySpendCustom.js";
12
+ // ABI for contractURI and uri functions
13
+ const CONTRACT_URI_ABI = [
14
+ {
15
+ inputs: [],
16
+ name: "contractURI",
17
+ outputs: [{ internalType: "string", name: "", type: "string" }],
18
+ stateMutability: "view",
19
+ type: "function",
20
+ },
21
+ {
22
+ inputs: [{ internalType: "uint256", name: "_tokenId", type: "uint256" }],
23
+ name: "uri",
24
+ outputs: [{ internalType: "string", name: "", type: "string" }],
25
+ stateMutability: "view",
26
+ type: "function",
27
+ },
28
+ ];
12
29
  export function AnySpendNFT({ isMainnet = true, loadOrder, mode = "modal", recipientAddress, nftContract, onSuccess, }) {
13
- const header = ({ anyspendPrice, isLoadingAnyspendPrice, }) => (_jsxs(_Fragment, { children: [_jsxs("div", { className: "relative size-[200px]", children: [_jsx("div", { className: "absolute inset-0 scale-95 bg-black/30 blur-md" }), _jsxs(GlareCard, { className: "overflow-hidden", children: [_jsx("img", { src: getIpfsUrl(nftContract.imageUrl), alt: nftContract.name, className: "size-full object-cover" }), _jsx("div", { className: "absolute inset-0 rounded-xl border border-white/10" })] }), _jsx(DropdownMenu, { nftContract: nftContract })] }), _jsxs("div", { className: "from-b3-react-background to-as-on-surface-1 mt-[-100px] w-full rounded-t-lg bg-gradient-to-t", children: [_jsx("div", { className: "h-[100px] w-full" }), _jsxs("div", { className: "mb-1 flex w-full flex-col items-center gap-2 p-5", children: [_jsx("span", { className: "font-sf-rounded text-2xl font-semibold", children: nftContract.name }), _jsx("div", { className: "flex w-fit items-center gap-1", children: anyspendPrice ? (_jsx(AnimatePresence, { mode: "wait", children: _jsx("div", { className: cn("text-as-primary group flex items-center text-3xl font-semibold transition-all", {
30
+ const [imageUrlWithFallback, setFallbackImageUrl] = useState(nftContract.imageUrl);
31
+ const [isLoadingFallback, setIsLoadingFallback] = useState(false);
32
+ // Fetch contract metadata when imageUrl is empty
33
+ useEffect(() => {
34
+ async function fetchContractMetadata() {
35
+ // fetch image Uri if not provided
36
+ if (nftContract.imageUrl || isLoadingFallback) {
37
+ return;
38
+ }
39
+ try {
40
+ setIsLoadingFallback(true);
41
+ // Use the chainIdToPublicClient utility function
42
+ const publicClient = chainIdToPublicClient(nftContract.chainId);
43
+ let metadataURI;
44
+ // Use uri function if tokenId is available, otherwise use contractURI
45
+ if (nftContract.tokenId !== null && nftContract.tokenId !== undefined) {
46
+ console.log("Using uri function with tokenId:", nftContract.tokenId);
47
+ metadataURI = await publicClient.readContract({
48
+ address: nftContract.contractAddress,
49
+ abi: CONTRACT_URI_ABI,
50
+ functionName: "uri",
51
+ args: [BigInt(nftContract.tokenId)],
52
+ });
53
+ }
54
+ else {
55
+ console.log("Using contractURI function");
56
+ metadataURI = await publicClient.readContract({
57
+ address: nftContract.contractAddress,
58
+ abi: CONTRACT_URI_ABI,
59
+ functionName: "contractURI",
60
+ });
61
+ }
62
+ if (metadataURI) {
63
+ // Fetch the metadata from IPFS
64
+ const metadataUrl = getIpfsUrl(metadataURI);
65
+ const response = await fetch(metadataUrl);
66
+ const metadata = await response.json();
67
+ if (metadata.image) {
68
+ const fallbackUrl = getIpfsUrl(metadata.image);
69
+ setFallbackImageUrl(fallbackUrl);
70
+ console.log("fallbackImageUrl", fallbackUrl);
71
+ }
72
+ }
73
+ }
74
+ catch (error) {
75
+ console.error("Error fetching contract metadata:", error);
76
+ }
77
+ finally {
78
+ setIsLoadingFallback(false);
79
+ }
80
+ }
81
+ fetchContractMetadata();
82
+ }, [nftContract.contractAddress, nftContract.chainId, nftContract.imageUrl, nftContract.tokenId]);
83
+ const header = ({ anyspendPrice, isLoadingAnyspendPrice, }) => (_jsxs(_Fragment, { children: [_jsxs("div", { className: "relative size-[200px]", children: [_jsx("div", { className: "absolute inset-0 scale-95 bg-black/30 blur-md" }), _jsxs(GlareCard, { className: "overflow-hidden", children: [imageUrlWithFallback && (_jsx("img", { src: imageUrlWithFallback, alt: nftContract.name, className: "size-full object-cover" })), _jsx("div", { className: "absolute inset-0 rounded-xl border border-white/10" })] }), _jsx(DropdownMenu, { nftContract: nftContract })] }), _jsxs("div", { className: "from-b3-react-background to-as-on-surface-1 mt-[-100px] w-full rounded-t-lg bg-gradient-to-t", children: [_jsx("div", { className: "h-[100px] w-full" }), _jsxs("div", { className: "mb-1 flex w-full flex-col items-center gap-2 p-5", children: [_jsx("span", { className: "font-sf-rounded text-2xl font-semibold", children: nftContract.name }), _jsx("div", { className: "flex w-fit items-center gap-1", children: anyspendPrice ? (_jsx(AnimatePresence, { mode: "wait", children: _jsx("div", { className: cn("text-as-primary group flex items-center text-3xl font-semibold transition-all", {
14
84
  "opacity-0": isLoadingAnyspendPrice,
15
85
  }), children: formatDisplayNumber(anyspendPrice?.data?.currencyIn?.amountUsd, { style: "currency" }) }) })) : (_jsx("div", { className: "h-[36px] w-full" })) })] })] })] }));
16
86
  return (_jsx(AnySpendCustom, { isMainnet: isMainnet, loadOrder: loadOrder, mode: mode, recipientAddress: recipientAddress, orderType: "mint_nft", dstChainId: nftContract.chainId, dstToken: nftContract.currency, dstAmount: nftContract.price, contractAddress: nftContract.contractAddress, encodedData: "0x", metadata: {
@@ -469,7 +469,9 @@ export const OrderDetails = memo(function OrderDetails({ isMainnet, mode = "moda
469
469
  toast.success("Copied to clipboard");
470
470
  }, children: _jsxs("div", { className: "flex items-center gap-2", children: [_jsxs("strong", { className: "border-as-brand text-as-primary border-b-2 pb-1 text-2xl font-semibold sm:text-xl", children: [roundedUpSrcAmount, " ", srcToken.symbol] }), _jsx(Copy, { className: "text-as-primary/50 hover:text-as-primary h-5 w-5 cursor-pointer transition-all duration-200" })] }) }), _jsxs(Badge, { variant: "outline", className: "flex h-10 items-center gap-2 px-3 py-1 pr-2 text-sm", children: ["on ", getChainName(order.srcChain), _jsx("img", { src: ALL_CHAINS[order.srcChain].logoUrl, alt: getChainName(order.srcChain), className: cn("h-6 rounded-full", order.srcChain === b3.id && "h-5 rounded-none") })] })] }), _jsx("span", { className: "text-as-primary/50 mb-1 mt-2", children: " to the address:" })] }), _jsx(CopyToClipboard, { text: order.globalAddress, onCopy: () => {
471
471
  toast.success("Copied to clipboard");
472
- }, children: _jsxs("div", { className: "bg-b3-react-background border-b3-react-border hover:border-as-brand group flex cursor-pointer items-center justify-between gap-4 rounded-lg border p-3 px-4 shadow-md transition-all duration-200", children: [_jsx("div", { className: "text-as-primary overflow-hidden text-ellipsis whitespace-nowrap text-sm", children: order.globalAddress }), _jsx(Copy, { className: "group-hover:text-as-brand text-as-primary/50 h-5 w-5 cursor-pointer transition-all duration-200" })] }) }), (account?.address || phantomWalletAddress) && !showQRCode ? (_jsxs("div", { className: "mb-4 mt-8 flex w-full flex-col items-center gap-4", children: [_jsxs("div", { className: "relative flex w-full flex-col items-center gap-2", children: [_jsx(ShinyButton, { accentColor: "hsl(var(--as-brand))", textColor: "text-white", className: "flex w-5/6 items-center gap-2 sm:px-0", disabled: txLoading || isSwitchingOrExecuting, onClick: handlePayment, children: txLoading ? (_jsxs(_Fragment, { children: ["Transaction Pending", _jsx(Loader2, { className: "ml-2 h-5 w-5 animate-spin" })] })) : (_jsxs(_Fragment, { children: [_jsx("span", { className: "pl-4 text-lg md:text-sm", children: "Pay from Connected Wallet" }), _jsx(ChevronRight, { className: "h-4 w-4" })] })) }), _jsxs("span", { className: "label-style text-as-primary/50 text-xs", children: ["Connected to:", " ", order.srcChain === RELAY_SOLANA_MAINNET_CHAIN_ID && phantomWalletAddress
472
+ }, children: _jsxs("div", { className: "bg-b3-react-background border-b3-react-border hover:border-as-brand group flex cursor-pointer items-center justify-between gap-4 rounded-lg border p-3 px-4 shadow-md transition-all duration-200", children: [_jsx("div", { className: "text-as-primary overflow-hidden text-ellipsis whitespace-nowrap text-sm", children: order.globalAddress }), _jsx(Copy, { className: "group-hover:text-as-brand text-as-primary/50 h-5 w-5 cursor-pointer transition-all duration-200" })] }) }), (account?.address || phantomWalletAddress) && !showQRCode ? (_jsxs("div", { className: "mb-4 mt-8 flex w-full flex-col items-center gap-4", children: [_jsxs("div", { className: "relative flex w-full flex-col items-center gap-2", children: [_jsx(ShinyButton, { accentColor: "hsl(var(--as-brand))", textColor: "text-white", className: "flex w-5/6 items-center gap-2 sm:px-0", disabled: txLoading || isSwitchingOrExecuting, onClick: handlePayment, children: txLoading ? (_jsxs(_Fragment, { children: ["Transaction Pending", _jsx(Loader2, { className: "ml-2 h-5 w-5 animate-spin" })] })) : (_jsxs(_Fragment, { children: [_jsx("span", { className: "pl-4 text-lg md:text-sm", children: order.srcChain === RELAY_SOLANA_MAINNET_CHAIN_ID && phantomWalletAddress
473
+ ? "Pay from Phantom Wallet"
474
+ : "Pay from Connected Wallet" }), _jsx(ChevronRight, { className: "h-4 w-4" })] })) }), _jsxs("span", { className: "label-style text-as-primary/50 text-xs", children: ["Connected to:", " ", order.srcChain === RELAY_SOLANA_MAINNET_CHAIN_ID && phantomWalletAddress
473
475
  ? centerTruncate(phantomWalletAddress, 6)
474
476
  : centerTruncate(account?.address || "", 6)] })] }), _jsxs("div", { className: "flex w-full flex-col items-center gap-2", children: [_jsxs(ShinyButton, { accentColor: colorMode === "dark" ? "#ffffff" : "#000000", className: "flex w-5/6 items-center gap-2 sm:px-0", onClick: () => setShowQRCode(true), children: [_jsx("span", { className: "pl-4 text-lg md:text-sm", children: "Pay from a different wallet" }), _jsx(ChevronRight, { className: "h-4 w-4" })] }), _jsxs("div", { className: "flex items-center gap-2", children: [_jsx(WalletMetamask, { className: "h-5 w-5", variant: "branded" }), _jsx(WalletCoinbase, { className: "h-5 w-5", variant: "branded" }), _jsx(WalletPhantom, { className: "h-5 w-5", variant: "branded" }), _jsx(WalletTrust, { className: "h-5 w-5", variant: "branded" }), _jsx(WalletWalletConnect, { className: "h-5 w-5", variant: "branded" }), _jsx("span", { className: "label-style text-as-primary/30 text-xs", children: "& more" })] })] })] })) : (_jsxs(motion.div, { initial: { opacity: 0, filter: "blur(10px)" }, animate: { opacity: 1, filter: "blur(0px)" }, transition: { duration: 0.5, ease: "easeInOut" }, className: "flex w-full items-center justify-evenly gap-4", children: [_jsxs("div", { className: "mt-8 flex flex-col items-center rounded-lg bg-white p-6 pb-3", children: [_jsx(QRCodeSVG, { value: getPaymentUrl(order.globalAddress, BigInt(order.srcAmount), order.srcTokenAddress === RELAY_ETH_ADDRESS ? "ETH" : order.srcTokenAddress), className: "max-w-[200px]" }), _jsxs("div", { className: "mt-3 flex items-center justify-center gap-2 text-sm", children: [_jsx("span", { className: "label-style text-as-brand/70 text-sm", children: "Scan with" }), _jsxs(TextLoop, { interval: 3, children: [_jsx(WalletMetamask, { className: "h-5 w-5", variant: "branded" }), _jsx(WalletCoinbase, { className: "h-5 w-5", variant: "branded" }), _jsx(WalletPhantom, { className: "h-5 w-5", variant: "branded" }), _jsx(WalletTrust, { className: "h-5 w-5", variant: "branded" }), _jsx(WalletWalletConnect, { className: "h-5 w-5", variant: "branded" })] })] })] }), _jsxs("div", { className: "flex flex-col gap-2", children: [account && (_jsxs(Button, { variant: "ghost", className: "text-as-primary w-full", onClick: handlePayment, children: ["Send Transaction ", _jsx(ChevronRight, { className: "ml-2 h-4 w-4" })] })), EVM_CHAINS[order.srcChain] ? (_jsxs(Button, { variant: "outline", className: "w-full", onClick: handlePayment, children: ["Open Metamask", _jsx(WalletMetamask, { className: "ml-2 h-5 w-5", variant: "branded" })] })) : null, _jsx("a", { href: handleCoinbaseRedirect(), children: _jsxs(Button, { variant: "outline", className: "w-full", children: ["Open Coinbase", _jsx(WalletCoinbase, { className: "ml-2 h-5 w-5", variant: "branded" })] }) }), _jsxs(Button, { variant: "outline", className: "w-full", onClick: () => initiatePhantomTransfer(order.srcAmount, order.srcTokenAddress, order.globalAddress), children: ["Open Phantom", _jsx(WalletPhantom, { className: "ml-2 h-5 w-5", variant: "branded" })] })] })] }))] })), _jsxs("div", { className: "bg-as-light-brand/30 w-full rounded-lg p-4 sm:p-2 sm:px-4", children: [_jsx("p", { className: "text-as-secondary mb-3 text-sm", children: "Continue on another device?" }), _jsxs("div", { className: "flex items-center gap-4", children: [_jsx(CopyToClipboard, { text: permalink, onCopy: () => {
475
477
  toast.success("Copied to clipboard");
@@ -1673,7 +1673,7 @@ export interface components {
1673
1673
  * @description NFT image URL
1674
1674
  * @example https://example.com/nft.png
1675
1675
  */
1676
- imageUrl: string;
1676
+ imageUrl: string | null;
1677
1677
  /**
1678
1678
  * @description NFT name
1679
1679
  * @example Cool NFT Collection
@@ -864,7 +864,7 @@ export const getV1NftsByContractAddress = (options) => {
864
864
  type: 'apiKey'
865
865
  }
866
866
  ],
867
- url: 'https://insight.thirdweb.com/v1/nfts/{contract_address}',
867
+ url: '/v1/nfts/{contract_address}',
868
868
  ...options
869
869
  });
870
870
  };
@@ -3,7 +3,7 @@ import { client } from "./generated/client.gen.js";
3
3
  (function () {
4
4
  // Set BASE URL
5
5
  client.setConfig({
6
- baseUrl: "https://insight.thirdweb.com",
6
+ baseUrl: "https://8333.insight.thirdweb.com",
7
7
  });
8
8
  // Interceptors for issues described here https://npc-labs.slack.com/archives/C070E6HNG85/p1742446793549779?thread_ts=1741637902.666019&cid=C070E6HNG85
9
9
  client.interceptors.request.use((request, options) => {
@@ -8,6 +8,7 @@ export declare const SOLANA_ASSOCIATED_TOKEN_ACCOUNT_PROGRAM_ID = "ATokenGPvbdGV
8
8
  export declare const SOLANA_TOKEN_2022_PROGRAM_ID = "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb";
9
9
  export declare const B3_TOKEN: components["schemas"]["Token"];
10
10
  export declare const USDC_BASE: components["schemas"]["Token"];
11
+ export declare const ETH_BASE: components["schemas"]["Token"];
11
12
  export declare const NFT_CONTRACTS: components["schemas"]["NftContract"][];
12
13
  export declare const DEFAULT_NFT_CONTRACT: {
13
14
  chainId: number;
@@ -15,7 +16,7 @@ export declare const DEFAULT_NFT_CONTRACT: {
15
16
  price: string;
16
17
  priceFormatted: string;
17
18
  currency: components["schemas"]["Token"];
18
- imageUrl: string;
19
+ imageUrl: string | null;
19
20
  name: string;
20
21
  description: string;
21
22
  tokenId: number | null;
@@ -1673,7 +1673,7 @@ export interface components {
1673
1673
  * @description NFT image URL
1674
1674
  * @example https://example.com/nft.png
1675
1675
  */
1676
- imageUrl: string;
1676
+ imageUrl: string | null;
1677
1677
  /**
1678
1678
  * @description NFT name
1679
1679
  * @example Cool NFT Collection
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@b3dotfun/sdk",
3
- "version": "0.0.9-alpha.8",
3
+ "version": "0.0.10",
4
4
  "source": "src/index.ts",
5
5
  "main": "./dist/cjs/index.js",
6
6
  "react-native": "./dist/cjs/index.native.js",
@@ -191,7 +191,7 @@
191
191
  ],
192
192
  "dependencies": {
193
193
  "@amplitude/analytics-browser": "2.14.0",
194
- "@b3dotfun/b3-api": "0.0.26",
194
+ "@b3dotfun/b3-api": "0.0.27",
195
195
  "@b3dotfun/basement-api": "0.0.11",
196
196
  "@b3dotfun/bondkit": "^0.1.17",
197
197
  "@chakra-ui/react": "2.10.7",
@@ -34,6 +34,17 @@ export const USDC_BASE: components["schemas"]["Token"] = {
34
34
  },
35
35
  };
36
36
 
37
+ export const ETH_BASE: components["schemas"]["Token"] = {
38
+ symbol: "ETH",
39
+ chainId: base.id,
40
+ address: "0x0000000000000000000000000000000000000000",
41
+ name: "Ethereum",
42
+ decimals: 18,
43
+ metadata: {
44
+ logoURI: "https://polygonscan.com/token/images/eth_32.png",
45
+ },
46
+ };
47
+
37
48
  export const NFT_CONTRACTS: components["schemas"]["NftContract"][] = [
38
49
  {
39
50
  chainId: base.id,
@@ -1,15 +1,34 @@
1
- import { ALL_CHAINS, getChainName, getExplorerAddressUrl } from "@b3dotfun/sdk/anyspend";
1
+ import { ALL_CHAINS, chainIdToPublicClient, getChainName, getExplorerAddressUrl } from "@b3dotfun/sdk/anyspend";
2
+ import { components } from "@b3dotfun/sdk/anyspend/types/api";
2
3
  import { GlareCard, Popover, PopoverContent, PopoverTrigger } from "@b3dotfun/sdk/global-account/react";
3
4
  import { cn } from "@b3dotfun/sdk/shared/utils";
4
5
  import { getIpfsUrl } from "@b3dotfun/sdk/shared/utils/ipfs";
6
+
5
7
  import { formatDisplayNumber, formatTokenAmount } from "@b3dotfun/sdk/shared/utils/number";
6
8
  import { AnimatePresence } from "framer-motion";
7
9
  import { MoreVertical } from "lucide-react";
8
- import { useState } from "react";
10
+ import { useEffect, useState } from "react";
9
11
  import { b3 } from "viem/chains";
10
- import { AnySpendCustom } from "./AnySpendCustom";
11
12
  import { GetQuoteResponse } from "../../types/api_req_res";
12
- import { components } from "@b3dotfun/sdk/anyspend/types/api";
13
+ import { AnySpendCustom } from "./AnySpendCustom";
14
+
15
+ // ABI for contractURI and uri functions
16
+ const CONTRACT_URI_ABI = [
17
+ {
18
+ inputs: [],
19
+ name: "contractURI",
20
+ outputs: [{ internalType: "string", name: "", type: "string" }],
21
+ stateMutability: "view",
22
+ type: "function",
23
+ },
24
+ {
25
+ inputs: [{ internalType: "uint256", name: "_tokenId", type: "uint256" }],
26
+ name: "uri",
27
+ outputs: [{ internalType: "string", name: "", type: "string" }],
28
+ stateMutability: "view",
29
+ type: "function",
30
+ },
31
+ ] as const;
13
32
 
14
33
  export function AnySpendNFT({
15
34
  isMainnet = true,
@@ -26,6 +45,65 @@ export function AnySpendNFT({
26
45
  nftContract: components["schemas"]["NftContract"];
27
46
  onSuccess?: (txHash?: string) => void;
28
47
  }) {
48
+ const [imageUrlWithFallback, setFallbackImageUrl] = useState<string | null>(nftContract.imageUrl);
49
+ const [isLoadingFallback, setIsLoadingFallback] = useState(false);
50
+
51
+ // Fetch contract metadata when imageUrl is empty
52
+ useEffect(() => {
53
+ async function fetchContractMetadata() {
54
+ // fetch image Uri if not provided
55
+ if (nftContract.imageUrl || isLoadingFallback) {
56
+ return;
57
+ }
58
+
59
+ try {
60
+ setIsLoadingFallback(true);
61
+
62
+ // Use the chainIdToPublicClient utility function
63
+ const publicClient = chainIdToPublicClient(nftContract.chainId);
64
+
65
+ let metadataURI: string;
66
+
67
+ // Use uri function if tokenId is available, otherwise use contractURI
68
+ if (nftContract.tokenId !== null && nftContract.tokenId !== undefined) {
69
+ console.log("Using uri function with tokenId:", nftContract.tokenId);
70
+ metadataURI = await publicClient.readContract({
71
+ address: nftContract.contractAddress as `0x${string}`,
72
+ abi: CONTRACT_URI_ABI,
73
+ functionName: "uri",
74
+ args: [BigInt(nftContract.tokenId)],
75
+ });
76
+ } else {
77
+ console.log("Using contractURI function");
78
+ metadataURI = await publicClient.readContract({
79
+ address: nftContract.contractAddress as `0x${string}`,
80
+ abi: CONTRACT_URI_ABI,
81
+ functionName: "contractURI",
82
+ });
83
+ }
84
+
85
+ if (metadataURI) {
86
+ // Fetch the metadata from IPFS
87
+ const metadataUrl = getIpfsUrl(metadataURI);
88
+ const response = await fetch(metadataUrl);
89
+ const metadata = await response.json();
90
+
91
+ if (metadata.image) {
92
+ const fallbackUrl = getIpfsUrl(metadata.image);
93
+ setFallbackImageUrl(fallbackUrl);
94
+ console.log("fallbackImageUrl", fallbackUrl);
95
+ }
96
+ }
97
+ } catch (error) {
98
+ console.error("Error fetching contract metadata:", error);
99
+ } finally {
100
+ setIsLoadingFallback(false);
101
+ }
102
+ }
103
+
104
+ fetchContractMetadata();
105
+ }, [nftContract.contractAddress, nftContract.chainId, nftContract.imageUrl, nftContract.tokenId]);
106
+
29
107
  const header = ({
30
108
  anyspendPrice,
31
109
  isLoadingAnyspendPrice,
@@ -37,7 +115,9 @@ export function AnySpendNFT({
37
115
  <div className="relative size-[200px]">
38
116
  <div className="absolute inset-0 scale-95 bg-black/30 blur-md"></div>
39
117
  <GlareCard className="overflow-hidden">
40
- <img src={getIpfsUrl(nftContract.imageUrl)} alt={nftContract.name} className="size-full object-cover" />
118
+ {imageUrlWithFallback && (
119
+ <img src={imageUrlWithFallback} alt={nftContract.name} className="size-full object-cover" />
120
+ )}
41
121
  <div className="absolute inset-0 rounded-xl border border-white/10"></div>
42
122
  </GlareCard>
43
123
 
@@ -992,7 +992,11 @@ export const OrderDetails = memo(function OrderDetails({
992
992
  </>
993
993
  ) : (
994
994
  <>
995
- <span className="pl-4 text-lg md:text-sm">Pay from Connected Wallet</span>
995
+ <span className="pl-4 text-lg md:text-sm">
996
+ {order.srcChain === RELAY_SOLANA_MAINNET_CHAIN_ID && phantomWalletAddress
997
+ ? "Pay from Phantom Wallet"
998
+ : "Pay from Connected Wallet"}
999
+ </span>
996
1000
  <ChevronRight className="h-4 w-4" />
997
1001
  </>
998
1002
  )}
@@ -1698,7 +1698,7 @@ export interface components {
1698
1698
  * @description NFT image URL
1699
1699
  * @example https://example.com/nft.png
1700
1700
  */
1701
- imageUrl: string;
1701
+ imageUrl: string | null;
1702
1702
  /**
1703
1703
  * @description NFT name
1704
1704
  * @example Cool NFT Collection
@@ -915,7 +915,7 @@ export const getV1NftsByContractAddress = <ThrowOnError extends boolean = false>
915
915
  type: 'apiKey'
916
916
  }
917
917
  ],
918
- url: 'https://insight.thirdweb.com/v1/nfts/{contract_address}',
918
+ url: '/v1/nfts/{contract_address}',
919
919
  ...options
920
920
  });
921
921
  };
@@ -4,7 +4,7 @@ import { client } from "./generated/client.gen";
4
4
  (function () {
5
5
  // Set BASE URL
6
6
  client.setConfig({
7
- baseUrl: "https://insight.thirdweb.com",
7
+ baseUrl: "https://8333.insight.thirdweb.com",
8
8
  });
9
9
 
10
10
  // Interceptors for issues described here https://npc-labs.slack.com/archives/C070E6HNG85/p1742446793549779?thread_ts=1741637902.666019&cid=C070E6HNG85