diff --git a/apps/dashboard/src/@/actions/getBalancesFromMoralis.ts b/apps/dashboard/src/@/actions/getBalancesFromMoralis.ts
index 9c82d9e850a..a7dc98f04fb 100644
--- a/apps/dashboard/src/@/actions/getBalancesFromMoralis.ts
+++ b/apps/dashboard/src/@/actions/getBalancesFromMoralis.ts
@@ -1,9 +1,8 @@
"use server";
-
-import { getThirdwebClient } from "@/constants/thirdweb.server";
import { defineDashboardChain } from "lib/defineDashboardChain";
import { ZERO_ADDRESS, isAddress, toTokens } from "thirdweb";
import { getWalletBalance } from "thirdweb/wallets";
+import { getUserThirdwebClient } from "../../app/api/lib/getAuthToken";
type BalanceQueryResponse = Array<{
balance: string;
@@ -24,6 +23,7 @@ export async function getTokenBalancesFromMoralis(params: {
error: string;
}
> {
+ const client = await getUserThirdwebClient();
const { contractAddress, chainId } = params;
if (!isAddress(contractAddress)) {
@@ -39,7 +39,7 @@ export async function getTokenBalancesFromMoralis(params: {
const balance = await getWalletBalance({
address: contractAddress,
chain,
- client: getThirdwebClient(),
+ client,
});
return [
{
diff --git a/apps/dashboard/src/@/actions/getWalletNFTs.ts b/apps/dashboard/src/@/actions/getWalletNFTs.ts
index 93e78575804..84f99007ab4 100644
--- a/apps/dashboard/src/@/actions/getWalletNFTs.ts
+++ b/apps/dashboard/src/@/actions/getWalletNFTs.ts
@@ -2,16 +2,16 @@
import {
generateAlchemyUrl,
- isAlchemySupported,
transformAlchemyResponseToNFT,
} from "lib/wallet/nfts/alchemy";
import {
generateMoralisUrl,
- isMoralisSupported,
transformMoralisResponseToNFT,
} from "lib/wallet/nfts/moralis";
import type { WalletNFT } from "lib/wallet/nfts/types";
import { getVercelEnv } from "../../lib/vercel-utils";
+import { isAlchemySupported } from "../../lib/wallet/nfts/isAlchemySupported";
+import { isMoralisSupported } from "../../lib/wallet/nfts/isMoralisSupported";
import { DASHBOARD_THIRDWEB_CLIENT_ID } from "../constants/env";
type WalletNFTApiReturn =
diff --git a/apps/dashboard/src/@/components/blocks/Avatars/GradientAvatar.stories.tsx b/apps/dashboard/src/@/components/blocks/Avatars/GradientAvatar.stories.tsx
index 121e4c1b3b4..880893e091e 100644
--- a/apps/dashboard/src/@/components/blocks/Avatars/GradientAvatar.stories.tsx
+++ b/apps/dashboard/src/@/components/blocks/Avatars/GradientAvatar.stories.tsx
@@ -1,7 +1,9 @@
import type { Meta, StoryObj } from "@storybook/react";
import { useState } from "react";
-import { BadgeContainer } from "../../../../stories/utils";
-import { getThirdwebClient } from "../../../constants/thirdweb.server";
+import {
+ BadgeContainer,
+ storybookThirdwebClient,
+} from "../../../../stories/utils";
import { Button } from "../../ui/button";
import { GradientAvatar } from "./GradientAvatar";
@@ -17,8 +19,6 @@ export const Variants: Story = {
args: {},
};
-const client = getThirdwebClient();
-
function Story() {
return (
@@ -29,7 +29,7 @@ function Story() {
id={undefined}
src={undefined}
className="size-20"
- client={client}
+ client={storybookThirdwebClient}
/>
@@ -38,7 +38,7 @@ function Story() {
id={"foo"}
src={undefined}
className="size-20"
- client={client}
+ client={storybookThirdwebClient}
/>
@@ -47,7 +47,7 @@ function Story() {
id={"foo"}
src={""}
className="size-20"
- client={client}
+ client={storybookThirdwebClient}
/>
@@ -56,7 +56,7 @@ function Story() {
id={"bar"}
src={""}
className="size-20"
- client={client}
+ client={storybookThirdwebClient}
/>
@@ -65,7 +65,7 @@ function Story() {
src="invalid-src"
id={undefined}
className="size-20"
- client={client}
+ client={storybookThirdwebClient}
/>
@@ -74,7 +74,7 @@ function Story() {
src="https://picsum.photos/200/300"
id={undefined}
className="size-20"
- client={client}
+ client={storybookThirdwebClient}
/>
@@ -83,7 +83,7 @@ function Story() {
src="ipfs://QmZbeJYEs7kCJHyQxjxU2SJUtjSAr4m87wzJFJUyWomKdj/Smily.svg"
id={undefined}
className="size-20"
- client={client}
+ client={storybookThirdwebClient}
/>
@@ -123,7 +123,7 @@ function ToggleTest() {
src={data?.src}
id={data?.id}
className="size-20"
- client={client}
+ client={storybookThirdwebClient}
/>
@@ -132,7 +132,7 @@ function ToggleTest() {
className="size-20"
src={data ? "invalid-src" : undefined}
id={undefined}
- client={client}
+ client={storybookThirdwebClient}
/>
diff --git a/apps/dashboard/src/@/components/blocks/Avatars/ProjectAvatar.stories.tsx b/apps/dashboard/src/@/components/blocks/Avatars/ProjectAvatar.stories.tsx
index 30674e33330..a39350dccc9 100644
--- a/apps/dashboard/src/@/components/blocks/Avatars/ProjectAvatar.stories.tsx
+++ b/apps/dashboard/src/@/components/blocks/Avatars/ProjectAvatar.stories.tsx
@@ -1,7 +1,9 @@
import type { Meta, StoryObj } from "@storybook/react";
import { useState } from "react";
-import { BadgeContainer } from "../../../../stories/utils";
-import { getThirdwebClient } from "../../../constants/thirdweb.server";
+import {
+ BadgeContainer,
+ storybookThirdwebClient,
+} from "../../../../stories/utils";
import { Button } from "../../ui/button";
import { ProjectAvatar } from "./ProjectAvatar";
@@ -18,19 +20,25 @@ export const Variants: Story = {
args: {},
};
-const client = getThirdwebClient();
-
function Story() {
return (
All images below are set with size-6 className
-
+
-
+
@@ -65,14 +73,18 @@ function ToggleTest() {
Src+Name is: {data ? "set" : "not set"}
-
+
diff --git a/apps/dashboard/src/@/constants/thirdweb.client.ts b/apps/dashboard/src/@/constants/thirdweb.client.ts
index 60e982e2159..731110348fb 100644
--- a/apps/dashboard/src/@/constants/thirdweb.client.ts
+++ b/apps/dashboard/src/@/constants/thirdweb.client.ts
@@ -2,12 +2,16 @@ import { useQuery } from "@tanstack/react-query";
import { useMemo } from "react";
import { useActiveAccount } from "thirdweb/react";
import type { GetAuthTokenResponse } from "../../app/api/auth/get-auth-token/route";
+import { LAST_USED_TEAM_ID } from "../../constants/cookies";
+import { getCookie } from "../../lib/cookie";
import { getThirdwebClient } from "./thirdweb.server";
// returns a thirdweb client with optional JWT passed i
export function useThirdwebClient(jwt?: string) {
const account = useActiveAccount();
+ const lastUsedTeamId = getCookie(LAST_USED_TEAM_ID);
+
const query = useQuery({
queryKey: ["jwt", account?.address],
// only enable the query if there is an account and no JWT is passed in directly
@@ -33,8 +37,12 @@ export function useThirdwebClient(jwt?: string) {
return useMemo(
// prefer jwt from props over the one from the token query if it exists
- () => getThirdwebClient(jwt || query.data),
- [jwt, query.data],
+ () =>
+ getThirdwebClient({
+ jwt: jwt || query.data,
+ teamId: lastUsedTeamId,
+ }),
+ [jwt, query.data, lastUsedTeamId],
);
}
diff --git a/apps/dashboard/src/@/constants/thirdweb.server.ts b/apps/dashboard/src/@/constants/thirdweb.server.ts
index cf73743d190..28cc1f3ac97 100644
--- a/apps/dashboard/src/@/constants/thirdweb.server.ts
+++ b/apps/dashboard/src/@/constants/thirdweb.server.ts
@@ -23,7 +23,14 @@ import { getZkPaymasterData } from "thirdweb/wallets/smart";
import { getVercelEnv } from "../../lib/vercel-utils";
// returns a thirdweb client with optional JWT passed in
-export function getThirdwebClient(jwt?: string) {
+export function getThirdwebClient(
+ options:
+ | {
+ jwt: string | null | undefined;
+ teamId: string | undefined;
+ }
+ | undefined,
+) {
if (getVercelEnv() !== "production") {
// if not on production: run this when creating a client to set the domains
setThirdwebDomains({
@@ -71,7 +78,8 @@ export function getThirdwebClient(jwt?: string) {
}
return createThirdwebClient({
- secretKey: jwt ? jwt : DASHBOARD_THIRDWEB_SECRET_KEY,
+ teamId: options?.teamId,
+ secretKey: options?.jwt ? options.jwt : DASHBOARD_THIRDWEB_SECRET_KEY,
clientId: DASHBOARD_THIRDWEB_CLIENT_ID,
config: {
storage: {
diff --git a/apps/dashboard/src/app/(dashboard)/(bridge)/bridge/components/client/UniversalBridgeEmbed.tsx b/apps/dashboard/src/app/(dashboard)/(bridge)/bridge/components/client/UniversalBridgeEmbed.tsx
index ccc20d1cc5f..dbb2e1673e3 100644
--- a/apps/dashboard/src/app/(dashboard)/(bridge)/bridge/components/client/UniversalBridgeEmbed.tsx
+++ b/apps/dashboard/src/app/(dashboard)/(bridge)/bridge/components/client/UniversalBridgeEmbed.tsx
@@ -1,17 +1,21 @@
"use client";
-import { getThirdwebClient } from "@/constants/thirdweb.server";
+
import { getSDKTheme } from "app/components/sdk-component-theme";
import { useV5DashboardChain } from "lib/v5-adapter";
import { useTheme } from "next-themes";
+import type { ThirdwebClient } from "thirdweb";
import { PayEmbed } from "thirdweb/react";
-export function UniversalBridgeEmbed({ chainId }: { chainId?: number }) {
+export function UniversalBridgeEmbed({
+ chainId,
+ client,
+}: { chainId?: number; client: ThirdwebClient }) {
const { theme } = useTheme();
const chain = useV5DashboardChain(chainId || 1);
return (
}) {
const { chainId } = searchParams;
+ const client = getThirdwebClient(undefined);
return (
-
+
{/* eslint-disable-next-line @next/next/no-img-element */}
diff --git a/apps/dashboard/src/app/(dashboard)/(bridge)/routes/components/server/routelist-card.tsx b/apps/dashboard/src/app/(dashboard)/(bridge)/routes/components/server/routelist-card.tsx
index 46774ad78bf..24ab0b5bc34 100644
--- a/apps/dashboard/src/app/(dashboard)/(bridge)/routes/components/server/routelist-card.tsx
+++ b/apps/dashboard/src/app/(dashboard)/(bridge)/routes/components/server/routelist-card.tsx
@@ -1,6 +1,6 @@
import { Card, CardContent, CardHeader } from "@/components/ui/card";
-import { getThirdwebClient } from "@/constants/thirdweb.server";
import { resolveSchemeWithErrorHandler } from "@/lib/resolveSchemeWithErrorHandler";
+import type { ThirdwebClient } from "thirdweb";
import { defineChain } from "thirdweb";
import { getChainMetadata } from "thirdweb/chains";
@@ -15,6 +15,7 @@ type RouteListCardProps = {
destinationTokenIconUri?: string | null;
destinationTokenSymbol: string;
destinationTokenName: string;
+ client: ThirdwebClient;
};
export async function RouteListCard({
@@ -26,6 +27,7 @@ export async function RouteListCard({
destinationTokenAddress,
destinationTokenIconUri,
destinationTokenName,
+ client,
}: RouteListCardProps) {
const [
originChain,
@@ -40,13 +42,13 @@ export async function RouteListCard({
originTokenIconUri
? resolveSchemeWithErrorHandler({
uri: originTokenIconUri,
- client: getThirdwebClient(),
+ client,
})
: undefined,
destinationTokenIconUri
? resolveSchemeWithErrorHandler({
uri: destinationTokenIconUri,
- client: getThirdwebClient(),
+ client,
})
: undefined,
]);
diff --git a/apps/dashboard/src/app/(dashboard)/(bridge)/routes/components/server/routelist-row.tsx b/apps/dashboard/src/app/(dashboard)/(bridge)/routes/components/server/routelist-row.tsx
index 27b68ca458f..aebf36e8418 100644
--- a/apps/dashboard/src/app/(dashboard)/(bridge)/routes/components/server/routelist-row.tsx
+++ b/apps/dashboard/src/app/(dashboard)/(bridge)/routes/components/server/routelist-row.tsx
@@ -1,7 +1,7 @@
import { CopyTextButton } from "@/components/ui/CopyTextButton";
import { TableCell, TableRow } from "@/components/ui/table";
-import { getThirdwebClient } from "@/constants/thirdweb.server";
import { resolveSchemeWithErrorHandler } from "@/lib/resolveSchemeWithErrorHandler";
+import type { ThirdwebClient } from "thirdweb";
import { defineChain, getChainMetadata } from "thirdweb/chains";
type RouteListRowProps = {
@@ -15,6 +15,7 @@ type RouteListRowProps = {
destinationTokenIconUri?: string | null;
destinationTokenSymbol?: string;
destinationTokenName?: string;
+ client: ThirdwebClient;
};
export async function RouteListRow({
@@ -26,6 +27,7 @@ export async function RouteListRow({
destinationTokenAddress,
destinationTokenIconUri,
destinationTokenSymbol,
+ client,
}: RouteListRowProps) {
const [
originChain,
@@ -40,13 +42,13 @@ export async function RouteListRow({
originTokenIconUri
? resolveSchemeWithErrorHandler({
uri: originTokenIconUri,
- client: getThirdwebClient(),
+ client,
})
: undefined,
destinationTokenIconUri
? resolveSchemeWithErrorHandler({
uri: destinationTokenIconUri,
- client: getThirdwebClient(),
+ client,
})
: undefined,
]);
diff --git a/apps/dashboard/src/app/(dashboard)/(bridge)/routes/components/server/routes-table.tsx b/apps/dashboard/src/app/(dashboard)/(bridge)/routes/components/server/routes-table.tsx
index 645a8ade655..4423b278d24 100644
--- a/apps/dashboard/src/app/(dashboard)/(bridge)/routes/components/server/routes-table.tsx
+++ b/apps/dashboard/src/app/(dashboard)/(bridge)/routes/components/server/routes-table.tsx
@@ -6,6 +6,7 @@ import {
TableHeader,
TableRow,
} from "@/components/ui/table";
+import { getThirdwebClient } from "@/constants/thirdweb.server";
import type { Address } from "thirdweb";
import { checksumAddress } from "thirdweb/utils";
import { getRoutes } from "../../../utils";
@@ -136,6 +137,7 @@ export async function RoutesData(props: {
const startIndex = (activePage - 1) * pageSize;
const endIndex = startIndex + pageSize;
const paginatedRoutes = routesToRender.slice(startIndex, endIndex);
+ const client = getThirdwebClient(undefined);
return (
<>
@@ -170,6 +172,7 @@ export async function RoutesData(props: {
destinationTokenIconUri={route.destinationToken.iconUri}
destinationTokenSymbol={route.destinationToken.symbol}
destinationTokenName={route.destinationToken.name}
+ client={client}
/>
))}
@@ -193,6 +196,7 @@ export async function RoutesData(props: {
destinationTokenIconUri={route.destinationToken.iconUri}
destinationTokenSymbol={route.destinationToken.symbol}
destinationTokenName={route.destinationToken.name}
+ client={client}
/>
))}
diff --git a/apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/(chainPage)/components/server/BuyFundsSection.tsx b/apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/(chainPage)/components/server/BuyFundsSection.tsx
index ea86946e9ab..64d81fda59b 100644
--- a/apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/(chainPage)/components/server/BuyFundsSection.tsx
+++ b/apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/(chainPage)/components/server/BuyFundsSection.tsx
@@ -1,12 +1,16 @@
import { ExternalLinkIcon } from "lucide-react";
import Link from "next/link";
+import type { ThirdwebClient } from "thirdweb";
import type { ChainMetadata } from "thirdweb/chains";
import { ChainIcon } from "../../../../components/server/chain-icon";
import { PayModalButton } from "../client/PayModal";
import { CreditCardIcon } from "../icons/CreditCardIcon";
import { SectionTitle } from "./SectionTitle";
-export function BuyFundsSection(props: { chain: ChainMetadata }) {
+export function BuyFundsSection(props: {
+ chain: ChainMetadata;
+ client: ThirdwebClient;
+}) {
const sanitizedChainName = props.chain.name.replace("Mainnet", "").trim();
return (
@@ -18,6 +22,7 @@ export function BuyFundsSection(props: { chain: ChainMetadata }) {
diff --git a/apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/(chainPage)/components/server/chain-header.tsx b/apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/(chainPage)/components/server/chain-header.tsx
index ab2140bae53..bd01374d3f0 100644
--- a/apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/(chainPage)/components/server/chain-header.tsx
+++ b/apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/(chainPage)/components/server/chain-header.tsx
@@ -1,6 +1,7 @@
import { Button } from "@/components/ui/button";
import { cn } from "@/lib/utils";
import Link from "next/link";
+import type { ThirdwebClient } from "thirdweb";
import type { ChainMetadata } from "thirdweb/chains";
import { mapV4ChainToV5Chain } from "../../../../../../../contexts/map-chains";
import { ChainIcon } from "../../../../components/server/chain-icon";
@@ -10,6 +11,7 @@ type ChainHeaderProps = {
headerImageUrl?: string;
logoUrl?: string;
chain: ChainMetadata;
+ client: ThirdwebClient;
};
// TODO: improve the behavior when clicking "Get started with thirdweb", currently just redirects to the dashboard
@@ -39,6 +41,7 @@ export function ChainHeader(props: ChainHeaderProps) {
{/* chain logo */}
diff --git a/apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/(chainPage)/opengraph-image.tsx b/apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/(chainPage)/opengraph-image.tsx
index bbc548926b7..2a785888be1 100644
--- a/apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/(chainPage)/opengraph-image.tsx
+++ b/apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/(chainPage)/opengraph-image.tsx
@@ -77,9 +77,10 @@ export default async function Image({
),
// download the chain icon if there is one
chain.icon?.url && hasWorkingChainIcon
- ? download({ uri: chain.icon.url, client: getThirdwebClient() }).then(
- (res) => res.arrayBuffer(),
- )
+ ? download({
+ uri: chain.icon.url,
+ client: getThirdwebClient(undefined),
+ }).then((res) => res.arrayBuffer())
: undefined,
// download the background image (based on chain)
fetch(
diff --git a/apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/(chainPage)/page.tsx b/apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/(chainPage)/page.tsx
index 1cd6f1e07bc..89722d94a56 100644
--- a/apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/(chainPage)/page.tsx
+++ b/apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/(chainPage)/page.tsx
@@ -1,5 +1,6 @@
import { CircleAlertIcon } from "lucide-react";
import { getRawAccount } from "../../../../account/settings/getAccount";
+import { getUserThirdwebClient } from "../../../../api/lib/getAuthToken";
import { getChain, getChainMetadata } from "../../utils";
import NextSteps from "./components/client/NextSteps";
import { BuyFundsSection } from "./components/server/BuyFundsSection";
@@ -18,6 +19,7 @@ export default async function Page(props: {
const chainMetadata = await getChainMetadata(chain.chainId);
const isDeprecated = chain.status === "deprecated";
+ const client = await getUserThirdwebClient();
const account = await getRawAccount();
return (
@@ -42,9 +44,9 @@ export default async function Page(props: {
{/* Faucet / Buy Funds */}
{chain.testnet ? (
-
+
) : chain.services.find((c) => c.service === "pay" && c.enabled) ? (
-
+
) : null}
{/* Chain Overview */}
diff --git a/apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/[contractAddress]/(marketplace)/components/list-button.tsx b/apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/[contractAddress]/(marketplace)/components/list-button.tsx
index d30fff1872a..4b382ba36db 100644
--- a/apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/[contractAddress]/(marketplace)/components/list-button.tsx
+++ b/apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/[contractAddress]/(marketplace)/components/list-button.tsx
@@ -10,12 +10,12 @@ import {
} from "@/components/ui/sheet";
import { TabButtons } from "@/components/ui/tabs";
import { ListerOnly } from "@3rdweb-sdk/react/components/roles/lister-only";
-import { isAlchemySupported } from "lib/wallet/nfts/alchemy";
-import { isMoralisSupported } from "lib/wallet/nfts/moralis";
import { PlusIcon } from "lucide-react";
import { useState } from "react";
import type { ThirdwebContract } from "thirdweb";
import { useActiveAccount } from "thirdweb/react";
+import { isAlchemySupported } from "../../../../../../../lib/wallet/nfts/isAlchemySupported";
+import { isMoralisSupported } from "../../../../../../../lib/wallet/nfts/isMoralisSupported";
import { CreateListingsForm } from "./list-form";
interface CreateListingButtonProps {
diff --git a/apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/[contractAddress]/(marketplace)/components/list-form.tsx b/apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/[contractAddress]/(marketplace)/components/list-form.tsx
index 29f96dc3c99..68aee9001ad 100644
--- a/apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/[contractAddress]/(marketplace)/components/list-form.tsx
+++ b/apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/[contractAddress]/(marketplace)/components/list-form.tsx
@@ -18,8 +18,6 @@ import { SolidityInput } from "contract-ui/components/solidity-inputs";
import { useTrack } from "hooks/analytics/useTrack";
import { useAllChainsData } from "hooks/chains/allChains";
import { useTxNotifications } from "hooks/useTxNotifications";
-import { isAlchemySupported } from "lib/wallet/nfts/alchemy";
-import { isMoralisSupported } from "lib/wallet/nfts/moralis";
import type { WalletNFT } from "lib/wallet/nfts/types";
import { CircleAlertIcon, InfoIcon } from "lucide-react";
import Link from "next/link";
@@ -56,6 +54,8 @@ import { shortenAddress } from "thirdweb/utils";
import { FormErrorMessage, FormHelperText, FormLabel } from "tw-components";
import { NFTMediaWithEmptyState } from "tw-components/nft-media";
import { shortenIfAddress } from "utils/usedapp-external";
+import { isAlchemySupported } from "../../../../../../../lib/wallet/nfts/isAlchemySupported";
+import { isMoralisSupported } from "../../../../../../../lib/wallet/nfts/isMoralisSupported";
const LIST_FORM_ID = "marketplace-list-form";
diff --git a/apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/[contractAddress]/_layout/contract-metadata.tsx b/apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/[contractAddress]/_layout/contract-metadata.tsx
index 316bb1a6e22..3b84562d93c 100644
--- a/apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/[contractAddress]/_layout/contract-metadata.tsx
+++ b/apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/[contractAddress]/_layout/contract-metadata.tsx
@@ -1,4 +1,3 @@
-import { getThirdwebClient } from "@/constants/thirdweb.server";
import {
type DashboardContractMetadata,
fetchDashboardContractMetadata,
@@ -32,6 +31,7 @@ export function ContractMetadata({
chain={chain}
address={contract.address}
externalLinks={externalLinks}
+ client={contract.client}
/>
);
}
@@ -43,7 +43,7 @@ export async function getContractMetadataHeaderData(
fetchDashboardContractMetadata(contract),
fetchPublishedContractsFromDeploy({
contract,
- client: getThirdwebClient(),
+ client: contract.client,
}),
]);
diff --git a/apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/[contractAddress]/_layout/metadata-header.tsx b/apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/[contractAddress]/_layout/metadata-header.tsx
index e398f70649f..550ff06169c 100644
--- a/apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/[contractAddress]/_layout/metadata-header.tsx
+++ b/apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/[contractAddress]/_layout/metadata-header.tsx
@@ -2,10 +2,10 @@
import { CopyAddressButton } from "@/components/ui/CopyAddressButton";
import { Button } from "@/components/ui/button";
-import { getThirdwebClient } from "@/constants/thirdweb.server";
import { ChainIconClient } from "components/icons/ChainIcon";
import { ExternalLinkIcon } from "lucide-react";
import Link from "next/link";
+import type { ThirdwebClient } from "thirdweb";
import type { ChainMetadata } from "thirdweb/chains";
import { MediaRenderer } from "thirdweb/react";
@@ -22,6 +22,7 @@ interface MetadataHeaderProps {
};
chain: ChainMetadata;
externalLinks?: ExternalLink[];
+ client: ThirdwebClient;
}
export const MetadataHeader: React.FC = ({
@@ -29,6 +30,7 @@ export const MetadataHeader: React.FC = ({
data,
chain,
externalLinks,
+ client,
}) => {
const cleanedChainName = chain?.name?.replace("Mainnet", "").trim();
const validBlockExplorers = chain?.explorers
@@ -56,7 +58,7 @@ export const MetadataHeader: React.FC = ({
m.name === "SuperChainInterop",
);
+ const client = coreContract.client;
const addRowMutation = useMutation({
mutationFn: async (chain: { chainId: number; name: string }) => {
if (coreContract.chain.id === chain.chainId) {
@@ -122,7 +123,7 @@ export function DataTable({
const c = defineChain(chain.chainId);
const code = await eth_getCode(
getRpcClient({
- client: getThirdwebClient(),
+ client: client,
chain: c,
}),
{ address: coreContract.address },
@@ -261,7 +262,7 @@ export function DataTable({
return (
@@ -324,7 +325,7 @@ export function DataTable({
getCoreRowModel: getCoreRowModel(),
});
- const deployContract = async (chainId: number) => {
+ const deployContract = async (chainId: number, client: ThirdwebClient) => {
try {
if (!activeAccount) {
throw new Error("No active account");
@@ -332,7 +333,6 @@ export function DataTable({
// eslint-disable-next-line no-restricted-syntax
const chain = defineChain(chainId);
- const client = getThirdwebClient();
const salt =
inputSalt || concatHex(["0x03", padHex("0x", { size: 31 })]).toString();
diff --git a/apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/[contractAddress]/layout.tsx b/apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/[contractAddress]/layout.tsx
index eb0dcf4bfde..a89f6b8dd44 100644
--- a/apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/[contractAddress]/layout.tsx
+++ b/apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/[contractAddress]/layout.tsx
@@ -1,6 +1,5 @@
import { getProjects } from "@/api/projects";
import { getTeams } from "@/api/team";
-import { getThirdwebClient } from "@/constants/thirdweb.server";
import type { Metadata } from "next";
import { notFound } from "next/navigation";
import { localhost } from "thirdweb/chains";
@@ -12,6 +11,7 @@ import { shortenIfAddress } from "../../../../../utils/usedapp-external";
import {
getAuthToken,
getAuthTokenWalletAddress,
+ getUserThirdwebClient,
} from "../../../../api/lib/getAuthToken";
import { NebulaFloatingChatButton } from "../../../../nebula-app/(app)/components/FloatingChat/FloatingChat";
import { ConfigureCustomChain } from "./_layout/ConfigureCustomChain";
@@ -52,7 +52,7 @@ export default async function Layout(props: {
getAuthTokenWalletAddress(),
]);
- const client = getThirdwebClient();
+ const client = await getUserThirdwebClient();
const teamsAndProjects = await getTeamsAndProjectsIfLoggedIn();
if (contract.chain.id === localhost.id) {
diff --git a/apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/[contractAddress]/modules/components/batchMetadata.stories.tsx b/apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/[contractAddress]/modules/components/batchMetadata.stories.tsx
index 546fa983002..9ab2287dc14 100644
--- a/apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/[contractAddress]/modules/components/batchMetadata.stories.tsx
+++ b/apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/[contractAddress]/modules/components/batchMetadata.stories.tsx
@@ -1,10 +1,9 @@
import { Checkbox } from "@/components/ui/checkbox";
-import { getThirdwebClient } from "@/constants/thirdweb.server";
import type { Meta, StoryObj } from "@storybook/react";
import { useMutation } from "@tanstack/react-query";
import { useState } from "react";
import { toast } from "sonner";
-import { BadgeContainer } from "stories/utils";
+import { BadgeContainer, storybookThirdwebClient } from "stories/utils";
import { ZERO_ADDRESS } from "thirdweb";
import { ConnectButton, ThirdwebProvider } from "thirdweb/react";
import type { TransactionError } from "../../../../../../../contexts/error-handler";
@@ -70,7 +69,7 @@ function Component() {
-
+
diff --git a/apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/[contractAddress]/modules/components/claimable.stories.tsx b/apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/[contractAddress]/modules/components/claimable.stories.tsx
index 8f7ad37b1dc..9b6076735c4 100644
--- a/apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/[contractAddress]/modules/components/claimable.stories.tsx
+++ b/apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/[contractAddress]/modules/components/claimable.stories.tsx
@@ -6,7 +6,6 @@ import {
SelectTrigger,
SelectValue,
} from "@/components/ui/select";
-import { getThirdwebClient } from "@/constants/thirdweb.server";
import type { Meta, StoryObj } from "@storybook/react";
import { useMutation } from "@tanstack/react-query";
import { subDays } from "date-fns";
@@ -15,6 +14,7 @@ import { toast } from "sonner";
import { NATIVE_TOKEN_ADDRESS, ZERO_ADDRESS } from "thirdweb";
import { ConnectButton, ThirdwebProvider } from "thirdweb/react";
import { checksumAddress } from "thirdweb/utils";
+import { storybookThirdwebClient } from "../../../../../../../stories/utils";
import {
type ClaimConditionFormValues,
type ClaimConditionValue,
@@ -102,7 +102,7 @@ function Component() {
-
+
diff --git a/apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/[contractAddress]/modules/components/getModuleInstalledParams.ts b/apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/[contractAddress]/modules/components/getModuleInstalledParams.ts
index edc54cd8e1f..e942650ab21 100644
--- a/apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/[contractAddress]/modules/components/getModuleInstalledParams.ts
+++ b/apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/[contractAddress]/modules/components/getModuleInstalledParams.ts
@@ -1,21 +1,23 @@
-import { getThirdwebClient } from "@/constants/thirdweb.server";
import {
fetchLatestPublishedContractVersion,
fetchPublishedContractVersions,
} from "components/contract-components/fetch-contracts-with-versions";
-import { isAddress } from "thirdweb";
+import { type ThirdwebClient, isAddress } from "thirdweb";
import type { FetchDeployMetadataResult } from "thirdweb/contract";
import { resolveAddress } from "thirdweb/extensions/ens";
import invariant from "tiny-invariant";
import type { ModuleMeta } from "./install-module-params";
-export async function getModuleInstalledParams(ext: ModuleMeta) {
+export async function getModuleInstalledParams(
+ ext: ModuleMeta,
+ client: ThirdwebClient,
+) {
// get all versions of the module
// if the publisher is an ens name, resolve it
const publisherAddress = isAddress(ext.publisherAddress)
? ext.publisherAddress
: await resolveAddress({
- client: getThirdwebClient(),
+ client,
name: ext.publisherAddress,
});
@@ -25,11 +27,13 @@ export async function getModuleInstalledParams(ext: ModuleMeta) {
publishedModule = await fetchLatestPublishedContractVersion(
publisherAddress,
ext.moduleName,
+ client,
);
} else {
const allPublishedModules = await fetchPublishedContractVersions(
publisherAddress,
ext.moduleName,
+ client,
);
publishedModule = allPublishedModules.find(
diff --git a/apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/[contractAddress]/modules/components/install-module-params.tsx b/apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/[contractAddress]/modules/components/install-module-params.tsx
index 18e29cff371..c43bc0981b6 100644
--- a/apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/[contractAddress]/modules/components/install-module-params.tsx
+++ b/apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/[contractAddress]/modules/components/install-module-params.tsx
@@ -1,3 +1,4 @@
+import { useThirdwebClient } from "@/constants/thirdweb.client";
import { FormControl } from "@chakra-ui/react";
import { useQuery } from "@tanstack/react-query";
import { SolidityInput } from "contract-ui/components/solidity-inputs";
@@ -20,12 +21,13 @@ export function useModuleInstallParams(props: {
module?: ModuleMeta;
isQueryEnabled: boolean;
}) {
+ const client = useThirdwebClient();
const { module, isQueryEnabled } = props;
return useQuery({
queryKey: ["useModuleInstallParams", module],
queryFn: async () => {
invariant(module, "module must be defined");
- return await getModuleInstalledParams(module);
+ return await getModuleInstalledParams(module, client);
},
enabled: !!(isQueryEnabled && module),
refetchOnWindowFocus: false,
diff --git a/apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/[contractAddress]/modules/components/mintable.stories.tsx b/apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/[contractAddress]/modules/components/mintable.stories.tsx
index 550b831564c..a018dd38eff 100644
--- a/apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/[contractAddress]/modules/components/mintable.stories.tsx
+++ b/apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/[contractAddress]/modules/components/mintable.stories.tsx
@@ -7,12 +7,11 @@ import {
SelectTrigger,
SelectValue,
} from "@/components/ui/select";
-import { getThirdwebClient } from "@/constants/thirdweb.server";
import type { Meta, StoryObj } from "@storybook/react";
import { useMutation } from "@tanstack/react-query";
import { useState } from "react";
import { toast } from "sonner";
-import { BadgeContainer } from "stories/utils";
+import { BadgeContainer, storybookThirdwebClient } from "stories/utils";
import { ConnectButton, ThirdwebProvider } from "thirdweb/react";
import {
type MintFormValues,
@@ -75,7 +74,7 @@ function Component() {
-
+
diff --git a/apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/[contractAddress]/modules/components/openEditionMetadata.stories.tsx b/apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/[contractAddress]/modules/components/openEditionMetadata.stories.tsx
index 6d7d0ee3c72..91ecf0d1138 100644
--- a/apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/[contractAddress]/modules/components/openEditionMetadata.stories.tsx
+++ b/apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/[contractAddress]/modules/components/openEditionMetadata.stories.tsx
@@ -1,10 +1,9 @@
import { Checkbox } from "@/components/ui/checkbox";
-import { getThirdwebClient } from "@/constants/thirdweb.server";
import type { Meta, StoryObj } from "@storybook/react";
import { useMutation } from "@tanstack/react-query";
import { useState } from "react";
import { toast } from "sonner";
-import { BadgeContainer } from "stories/utils";
+import { BadgeContainer, storybookThirdwebClient } from "stories/utils";
import { ConnectButton, ThirdwebProvider } from "thirdweb/react";
import {
OpenEditionMetadataModuleUI,
@@ -56,7 +55,7 @@ function Component() {
-
+
diff --git a/apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/[contractAddress]/modules/components/royalty.stories.tsx b/apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/[contractAddress]/modules/components/royalty.stories.tsx
index 83b0f3769cb..38e9b03e9be 100644
--- a/apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/[contractAddress]/modules/components/royalty.stories.tsx
+++ b/apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/[contractAddress]/modules/components/royalty.stories.tsx
@@ -1,10 +1,9 @@
import { Checkbox } from "@/components/ui/checkbox";
-import { getThirdwebClient } from "@/constants/thirdweb.server";
import type { Meta, StoryObj } from "@storybook/react";
import { useMutation } from "@tanstack/react-query";
import { useState } from "react";
import { toast } from "sonner";
-import { BadgeContainer } from "stories/utils";
+import { BadgeContainer, storybookThirdwebClient } from "stories/utils";
import { ConnectButton, ThirdwebProvider } from "thirdweb/react";
import {
type DefaultRoyaltyFormValues,
@@ -70,7 +69,7 @@ function Component() {
-
+
diff --git a/apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/[contractAddress]/modules/components/transferable.stories.tsx b/apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/[contractAddress]/modules/components/transferable.stories.tsx
index 50d57fa3afd..e047028ff2e 100644
--- a/apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/[contractAddress]/modules/components/transferable.stories.tsx
+++ b/apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/[contractAddress]/modules/components/transferable.stories.tsx
@@ -1,10 +1,9 @@
import { Checkbox } from "@/components/ui/checkbox";
-import { getThirdwebClient } from "@/constants/thirdweb.server";
import type { Meta, StoryObj } from "@storybook/react";
import { useMutation } from "@tanstack/react-query";
import { useState } from "react";
import { toast } from "sonner";
-import { BadgeContainer } from "stories/utils";
+import { BadgeContainer, storybookThirdwebClient } from "stories/utils";
import { ConnectButton, ThirdwebProvider } from "thirdweb/react";
import {
type TransferableModuleFormValues,
@@ -74,7 +73,7 @@ function Component() {
-
+
diff --git a/apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/[contractAddress]/overview/components/published-by-ui.tsx b/apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/[contractAddress]/overview/components/published-by-ui.tsx
index 4e70eaae6e1..02702516bf9 100644
--- a/apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/[contractAddress]/overview/components/published-by-ui.tsx
+++ b/apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/[contractAddress]/overview/components/published-by-ui.tsx
@@ -54,7 +54,7 @@ export async function getPublishedByCardProps(params: {
let publisherAddressOrEns = publishedContractToShow.publisher;
if (!isValidENSName(publishedContractToShow.publisher)) {
try {
- const res = await resolveEns(publishedContractToShow.publisher);
+ const res = await resolveEns(publishedContractToShow.publisher, client);
if (res.ensName) {
publisherAddressOrEns = res.ensName;
}
@@ -147,6 +147,7 @@ export function PublishedByUI(props: {
publisher: string;
version: string | undefined;
isBeta: boolean;
+ client: ThirdwebClient;
}) {
return (
);
}
diff --git a/apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/[contractAddress]/overview/components/published-by.server.tsx b/apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/[contractAddress]/overview/components/published-by.server.tsx
index 653ebd266fd..9a9f392bda1 100644
--- a/apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/[contractAddress]/overview/components/published-by.server.tsx
+++ b/apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/[contractAddress]/overview/components/published-by.server.tsx
@@ -1,4 +1,3 @@
-import { getThirdwebClient } from "@/constants/thirdweb.server";
import type { ThirdwebContract } from "thirdweb";
import { getAuthTokenWalletAddress } from "../../../../../../api/lib/getAuthToken";
import { PublishedByUI, getPublishedByCardProps } from "./published-by-ui";
@@ -8,12 +7,11 @@ interface PublishedByProps {
}
export const PublishedBy: React.FC = async ({ contract }) => {
- const client = getThirdwebClient();
const address = await getAuthTokenWalletAddress();
const props = await getPublishedByCardProps({
address,
contract,
- client,
+ client: contract.client,
});
if (!props) {
@@ -27,6 +25,7 @@ export const PublishedBy: React.FC = async ({ contract }) => {
name={props.name}
publisher={props.publisher}
version={props.version}
+ client={contract.client}
/>
);
};
diff --git a/apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/tx/[txHash]/page.tsx b/apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/tx/[txHash]/page.tsx
index 750a2c7d72c..73c16296572 100644
--- a/apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/tx/[txHash]/page.tsx
+++ b/apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/tx/[txHash]/page.tsx
@@ -1,6 +1,5 @@
import { Badge } from "@/components/ui/badge";
import { Separator } from "@/components/ui/separator";
-import { getThirdwebClient } from "@/constants/thirdweb.server";
import { mapV4ChainToV5Chain } from "contexts/map-chains";
import { ZERO_ADDRESS, toTokens } from "thirdweb";
import {
@@ -10,14 +9,14 @@ import {
getRpcClient,
} from "thirdweb/rpc";
import { hexToNumber, shortenAddress, toEther } from "thirdweb/utils";
+import { getUserThirdwebClient } from "../../../../../api/lib/getAuthToken";
import { getChain } from "../../../utils";
export default async function Page(props: {
params: Promise<{ chain_id: string; txHash: `0x${string}` }>;
}) {
const params = await props.params;
- // consider if we want to pass the JWT here, likely no need to do it but we could?
- const client = getThirdwebClient();
+ const client = await getUserThirdwebClient();
const chain = await getChain(params.chain_id);
const rpcRequest = getRpcClient({
diff --git a/apps/dashboard/src/app/(dashboard)/(chain)/chainlist/[chain_type]/page.tsx b/apps/dashboard/src/app/(dashboard)/(chain)/chainlist/[chain_type]/page.tsx
index cab118039a2..448b414bd7f 100644
--- a/apps/dashboard/src/app/(dashboard)/(chain)/chainlist/[chain_type]/page.tsx
+++ b/apps/dashboard/src/app/(dashboard)/(chain)/chainlist/[chain_type]/page.tsx
@@ -14,7 +14,10 @@ import {
import { ChevronDownIcon } from "lucide-react";
import { headers } from "next/headers";
import Link from "next/link";
-import { getAuthToken } from "../../../../api/lib/getAuthToken";
+import {
+ getAuthToken,
+ getUserThirdwebClient,
+} from "../../../../api/lib/getAuthToken";
import {
AllFilters,
ChainOptionsFilter,
@@ -80,6 +83,8 @@ export default async function ChainListLayout(props: {
? "table"
: "grid";
+ const client = await getUserThirdwebClient();
+
return (
<>
@@ -150,6 +155,7 @@ export default async function ChainListLayout(props: {
searchParams={searchParams}
activeView={activeView}
isLoggedIn={!!authToken}
+ client={client}
/>
>
diff --git a/apps/dashboard/src/app/(dashboard)/(chain)/chainlist/components/server/chain-table.tsx b/apps/dashboard/src/app/(dashboard)/(chain)/chainlist/components/server/chain-table.tsx
index 51fafdfe7cb..47d48c6c6cf 100644
--- a/apps/dashboard/src/app/(dashboard)/(chain)/chainlist/components/server/chain-table.tsx
+++ b/apps/dashboard/src/app/(dashboard)/(chain)/chainlist/components/server/chain-table.tsx
@@ -7,6 +7,7 @@ import {
TableRow,
} from "@/components/ui/table";
import Fuse from "fuse.js";
+import type { ThirdwebClient } from "thirdweb";
import { StarButton } from "../../../components/client/star-button";
import type {
ChainMetadataWithServices,
@@ -141,6 +142,7 @@ export async function ChainsData(props: {
searchParams: SearchParams;
activeView: "table" | "grid";
isLoggedIn: boolean;
+ client: ThirdwebClient;
}) {
const { chainsToRender, totalCount, filteredCount } = await getChainsToRender(
props.searchParams,
@@ -177,6 +179,7 @@ export async function ChainsData(props: {
{paginatedChains.map((chain) => (
(
-
+
{favoriteButton &&
{favoriteButton}
}
-
+
@@ -76,6 +81,7 @@ export default async function ChainListPage(props: {
searchParams={searchParams}
activeView={activeView}
isLoggedIn={!!authToken}
+ client={client}
/>
);
diff --git a/apps/dashboard/src/app/(dashboard)/(chain)/components/server/chain-icon.tsx b/apps/dashboard/src/app/(dashboard)/(chain)/components/server/chain-icon.tsx
index e57a1c77945..e4e847c7bad 100644
--- a/apps/dashboard/src/app/(dashboard)/(chain)/components/server/chain-icon.tsx
+++ b/apps/dashboard/src/app/(dashboard)/(chain)/components/server/chain-icon.tsx
@@ -1,20 +1,21 @@
/* eslint-disable @next/next/no-img-element */
import "server-only";
import { DASHBOARD_THIRDWEB_SECRET_KEY } from "@/constants/env";
-import { getThirdwebClient } from "@/constants/thirdweb.server";
import { resolveSchemeWithErrorHandler } from "@/lib/resolveSchemeWithErrorHandler";
import { cn } from "@/lib/utils";
+import type { ThirdwebClient } from "thirdweb";
import { fallbackChainIcon } from "../../../../../utils/chain-icons";
export async function ChainIcon(props: {
iconUrl?: string;
className?: string;
+ client: ThirdwebClient;
}) {
if (props.iconUrl) {
let imageLink = fallbackChainIcon;
const resolved = resolveSchemeWithErrorHandler({
- client: getThirdwebClient(),
+ client: props.client,
uri: props.iconUrl,
});
diff --git a/apps/dashboard/src/app/(dashboard)/contracts/deploy/[compiler_uri]/page.tsx b/apps/dashboard/src/app/(dashboard)/contracts/deploy/[compiler_uri]/page.tsx
index b49bdd73970..42ff9f34fd5 100644
--- a/apps/dashboard/src/app/(dashboard)/contracts/deploy/[compiler_uri]/page.tsx
+++ b/apps/dashboard/src/app/(dashboard)/contracts/deploy/[compiler_uri]/page.tsx
@@ -1,6 +1,6 @@
-import { getThirdwebClient } from "@/constants/thirdweb.server";
import { notFound } from "next/navigation";
import { fetchDeployMetadata } from "thirdweb/contract";
+import { getUserThirdwebClient } from "../../../../api/lib/getAuthToken";
import { DeployContractInfo } from "../../../published-contract/components/contract-info";
import { DeployFormForUri } from "../../../published-contract/components/uri-based-deploy";
@@ -13,8 +13,10 @@ type DirectDeployPageProps = {
export default async function DirectDeployPage(props: DirectDeployPageProps) {
const params = await props.params;
const parsedUri = decodeURIComponent(params.compiler_uri);
+ const client = await getUserThirdwebClient();
+
const metadata = await fetchDeployMetadata({
- client: getThirdwebClient(),
+ client,
// force `ipfs://` prefix
uri: parsedUri.startsWith("ipfs://") ? parsedUri : `ipfs://${parsedUri}`,
}).catch(() => null);
@@ -30,6 +32,7 @@ export default async function DirectDeployPage(props: DirectDeployPageProps) {
displayName={metadata.displayName}
description={metadata.description}
logo={metadata.logo}
+ client={client}
/>
}>
-
+
);
diff --git a/apps/dashboard/src/app/(dashboard)/contracts/publish/[publish_uri]/page.tsx b/apps/dashboard/src/app/(dashboard)/contracts/publish/[publish_uri]/page.tsx
index 5ec794acb43..ef084510458 100644
--- a/apps/dashboard/src/app/(dashboard)/contracts/publish/[publish_uri]/page.tsx
+++ b/apps/dashboard/src/app/(dashboard)/contracts/publish/[publish_uri]/page.tsx
@@ -1,10 +1,10 @@
import { ChakraProviderSetup } from "@/components/ChakraProviderSetup";
import { getActiveAccountCookie, getJWTCookie } from "@/constants/cookie";
-import { getThirdwebClient } from "@/constants/thirdweb.server";
import { ContractPublishForm } from "components/contract-components/contract-publish-form";
import { revalidatePath } from "next/cache";
import { notFound, redirect } from "next/navigation";
import { fetchDeployMetadata } from "thirdweb/contract";
+import { getUserThirdwebClient } from "../../../../api/lib/getAuthToken";
import { getLatestPublishedContractsWithPublisherMapping } from "../../../published-contract/[publisher]/[contract_id]/utils/getPublishedContractsWithPublisherMapping";
type DirectDeployPageProps = {
@@ -22,9 +22,10 @@ export default async function PublishContractPage(
? decodedPublishUri
: `ipfs://${decodedPublishUri}`;
+ const client = await getUserThirdwebClient();
const publishMetadataFromUri = await fetchDeployMetadata({
uri: publishUri,
- client: getThirdwebClient(),
+ client,
}).catch(() => null);
if (!publishMetadataFromUri) {
@@ -50,6 +51,7 @@ export default async function PublishContractPage(
await getLatestPublishedContractsWithPublisherMapping({
publisher: address,
contract_id: publishMetadataFromUri.name,
+ client,
});
if (publishedContract) {
diff --git a/apps/dashboard/src/app/(dashboard)/contracts/publish/page.tsx b/apps/dashboard/src/app/(dashboard)/contracts/publish/page.tsx
index e5eebee4511..ae672fddb8e 100644
--- a/apps/dashboard/src/app/(dashboard)/contracts/publish/page.tsx
+++ b/apps/dashboard/src/app/(dashboard)/contracts/publish/page.tsx
@@ -3,6 +3,7 @@ import { DeployableContractTable } from "components/contract-components/contract
import Link from "next/link";
import { notFound } from "next/navigation";
import { Suspense } from "react";
+import { getUserThirdwebClient } from "../../../api/lib/getAuthToken";
export default async function PublishMultipleContractsPage(props: {
searchParams?: Promise<{
@@ -11,6 +12,7 @@ export default async function PublishMultipleContractsPage(props: {
}) {
const searchParams = await props.searchParams;
const ipfsHashes = searchParams?.ipfs;
+ const client = await getUserThirdwebClient();
if (!ipfsHashes || !Array.isArray(ipfsHashes) || ipfsHashes.length === 0) {
notFound();
@@ -35,7 +37,11 @@ export default async function PublishMultipleContractsPage(props: {
}>
-
+
);
diff --git a/apps/dashboard/src/app/(dashboard)/explore/[category]/page.tsx b/apps/dashboard/src/app/(dashboard)/explore/[category]/page.tsx
index 97a27b5d640..2ac822e4a66 100644
--- a/apps/dashboard/src/app/(dashboard)/explore/[category]/page.tsx
+++ b/apps/dashboard/src/app/(dashboard)/explore/[category]/page.tsx
@@ -16,11 +16,13 @@ import type { Metadata } from "next";
import Link from "next/link";
import { notFound } from "next/navigation";
import { Suspense } from "react";
+import type { ThirdwebClient } from "thirdweb";
type ExploreCategoryPageProps = {
params: Promise<{
category: string;
}>;
+ client: ThirdwebClient;
};
export async function generateMetadata(
@@ -102,6 +104,7 @@ export default async function ExploreCategoryPage(
key={publisher + contractId + overrides?.title}
>
@@ -37,7 +40,7 @@ export default async function ExplorePage() {
{Math.floor(EXPLORE_PAGE_DATA.length / 2) === idx && (
)}
-
+
))}
diff --git a/apps/dashboard/src/app/(dashboard)/profile/[addressOrEns]/ProfileUI.tsx b/apps/dashboard/src/app/(dashboard)/profile/[addressOrEns]/ProfileUI.tsx
index ae14e98da8b..d4a78065d36 100644
--- a/apps/dashboard/src/app/(dashboard)/profile/[addressOrEns]/ProfileUI.tsx
+++ b/apps/dashboard/src/app/(dashboard)/profile/[addressOrEns]/ProfileUI.tsx
@@ -1,14 +1,16 @@
import { Spinner } from "@/components/ui/Spinner/Spinner";
import { fetchPublishedContracts } from "components/contract-components/fetchPublishedContracts";
import { Suspense } from "react";
+import type { ThirdwebClient } from "thirdweb";
import { ProfileHeader } from "./components/profile-header";
import { PublishedContracts } from "./components/published-contracts";
export function ProfileUI(props: {
profileAddress: string;
ensName: string | undefined;
+ client: ThirdwebClient;
}) {
- const { profileAddress, ensName } = props;
+ const { profileAddress, ensName, client } = props;
return (
@@ -25,6 +27,7 @@ export function ProfileUI(props: {
@@ -37,10 +40,12 @@ export function ProfileUI(props: {
async function AsyncPublishedContracts(props: {
publisherAddress: string;
publisherEnsName: string | undefined;
+ client: ThirdwebClient;
}) {
- const publishedContracts = await fetchPublishedContracts(
- props.publisherAddress,
- );
+ const publishedContracts = await fetchPublishedContracts({
+ address: props.publisherAddress,
+ client: props.client,
+ });
if (publishedContracts.length === 0) {
return (
@@ -54,6 +59,7 @@ async function AsyncPublishedContracts(props: {
);
}
diff --git a/apps/dashboard/src/app/(dashboard)/profile/[addressOrEns]/components/PublishedContractTable.tsx b/apps/dashboard/src/app/(dashboard)/profile/[addressOrEns]/components/PublishedContractTable.tsx
index 026f9c33411..afae10b7c64 100644
--- a/apps/dashboard/src/app/(dashboard)/profile/[addressOrEns]/components/PublishedContractTable.tsx
+++ b/apps/dashboard/src/app/(dashboard)/profile/[addressOrEns]/components/PublishedContractTable.tsx
@@ -18,12 +18,14 @@ import { ShieldCheckIcon } from "lucide-react";
import Link from "next/link";
import { useMemo } from "react";
import { type Column, type Row, useTable } from "react-table";
+import type { ThirdwebClient } from "thirdweb";
import type { PublishedContractDetails } from "../../../../../components/contract-components/hooks";
interface PublishedContractTableProps {
contractDetails: ContractDataInput[];
footer?: React.ReactNode;
publisherEnsName: string | undefined;
+ client: ThirdwebClient;
}
type ContractDataInput = PublishedContractDetails;
@@ -57,7 +59,7 @@ export function PublishedContractTable(props: PublishedContractTableProps) {
Cell: (cell: any) => (
}
@@ -114,7 +116,7 @@ export function PublishedContractTable(props: PublishedContractTableProps) {
className="relative z-10 h-auto w-auto p-2"
>
>;
publisherEnsName: string | undefined;
+ client: ThirdwebClient;
}
export const PublishedContracts: React.FC = ({
limit = 10,
publishedContracts,
publisherEnsName,
+ client,
}) => {
const [showMoreLimit, setShowMoreLimit] = useState(10);
const slicedData = publishedContracts.slice(0, showMoreLimit);
return (
);
}
export async function generateMetadata(props: PageProps): Promise {
const params = await props.params;
- const resolvedInfo = await resolveAddressAndEns(params.addressOrEns);
+ const client = getThirdwebClient(undefined);
+ const resolvedInfo = await resolveAddressAndEns(params.addressOrEns, client);
if (!resolvedInfo) {
return notFound();
diff --git a/apps/dashboard/src/app/(dashboard)/profile/[addressOrEns]/resolveAddressAndEns.tsx b/apps/dashboard/src/app/(dashboard)/profile/[addressOrEns]/resolveAddressAndEns.tsx
index fb6579422d0..3265dc743f7 100644
--- a/apps/dashboard/src/app/(dashboard)/profile/[addressOrEns]/resolveAddressAndEns.tsx
+++ b/apps/dashboard/src/app/(dashboard)/profile/[addressOrEns]/resolveAddressAndEns.tsx
@@ -1,4 +1,4 @@
-import { getAddress, isAddress } from "thirdweb";
+import { type ThirdwebClient, getAddress, isAddress } from "thirdweb";
import { isValidENSName } from "thirdweb/utils";
import { mapThirdwebPublisher } from "../../../../components/contract-components/fetch-contracts-with-versions";
import { resolveEns } from "../../../../lib/ens";
@@ -9,9 +9,10 @@ type ResolvedAddressInfo = {
};
export async function resolveAddressAndEns(
addressOrEns: string,
+ client: ThirdwebClient,
): Promise {
if (isAddress(addressOrEns)) {
- const res = await resolveEns(addressOrEns).catch(() => null);
+ const res = await resolveEns(addressOrEns, client).catch(() => null);
return {
address: getAddress(addressOrEns),
ensName: res?.ensName || undefined,
@@ -20,7 +21,7 @@ export async function resolveAddressAndEns(
if (isValidENSName(addressOrEns)) {
const mappedEns = mapThirdwebPublisher(addressOrEns);
- const res = await resolveEns(mappedEns).catch(() => null);
+ const res = await resolveEns(mappedEns, client).catch(() => null);
if (res?.address) {
return {
address: getAddress(res?.address),
diff --git a/apps/dashboard/src/app/(dashboard)/published-contract/[publisher]/[contract_id]/[version]/deploy/page.tsx b/apps/dashboard/src/app/(dashboard)/published-contract/[publisher]/[contract_id]/[version]/deploy/page.tsx
index ed97daf37e1..d8955a4cc09 100644
--- a/apps/dashboard/src/app/(dashboard)/published-contract/[publisher]/[contract_id]/[version]/deploy/page.tsx
+++ b/apps/dashboard/src/app/(dashboard)/published-contract/[publisher]/[contract_id]/[version]/deploy/page.tsx
@@ -1,3 +1,4 @@
+import { getUserThirdwebClient } from "../../../../../../api/lib/getAuthToken";
import { DeployFormForPublishInfo } from "../../../../components/publish-based-deploy";
import { moduleFromBase64 } from "../../../../utils/module-base-64";
@@ -21,5 +22,10 @@ export default async function PublishedContractVersionDeployPage(props: {
const modules =
moduleParam?.map((m) => moduleFromBase64(m)).filter((m) => m !== null) ||
[];
- return ;
+
+ const client = await getUserThirdwebClient();
+
+ return (
+
+ );
}
diff --git a/apps/dashboard/src/app/(dashboard)/published-contract/[publisher]/[contract_id]/[version]/opengraph-image.tsx b/apps/dashboard/src/app/(dashboard)/published-contract/[publisher]/[contract_id]/[version]/opengraph-image.tsx
index 9f9d25d4428..0976b5ba077 100644
--- a/apps/dashboard/src/app/(dashboard)/published-contract/[publisher]/[contract_id]/[version]/opengraph-image.tsx
+++ b/apps/dashboard/src/app/(dashboard)/published-contract/[publisher]/[contract_id]/[version]/opengraph-image.tsx
@@ -20,16 +20,17 @@ export default async function Image(props: {
version: string;
};
}) {
- const client = getThirdwebClient();
+ const client = getThirdwebClient(undefined);
const { publisher, contract_id } = props.params;
const [publishedContracts, socialProfiles] = await Promise.all([
getPublishedContractsWithPublisherMapping({
publisher: publisher,
contract_id: contract_id,
+ client,
}),
getSocialProfiles({
- address: (await resolveEns(publisher)).address || publisher,
+ address: (await resolveEns(publisher, client)).address || publisher,
client,
}),
]);
diff --git a/apps/dashboard/src/app/(dashboard)/published-contract/[publisher]/[contract_id]/[version]/page.tsx b/apps/dashboard/src/app/(dashboard)/published-contract/[publisher]/[contract_id]/[version]/page.tsx
index 9f7fa2820ad..c755c3cb8d5 100644
--- a/apps/dashboard/src/app/(dashboard)/published-contract/[publisher]/[contract_id]/[version]/page.tsx
+++ b/apps/dashboard/src/app/(dashboard)/published-contract/[publisher]/[contract_id]/[version]/page.tsx
@@ -1,6 +1,5 @@
import { ChakraProviderSetup } from "@/components/ChakraProviderSetup";
import { Separator } from "@/components/ui/separator";
-import { getThirdwebClient } from "@/constants/thirdweb.server";
import { SimpleGrid } from "@chakra-ui/react";
import { fetchPublishedContractVersions } from "components/contract-components/fetch-contracts-with-versions";
import { PublishedContract } from "components/contract-components/published-contract";
@@ -8,9 +7,9 @@ import { notFound } from "next/navigation";
import { isAddress } from "thirdweb";
import { resolveAddress } from "thirdweb/extensions/ens";
import { getRawAccount } from "../../../../../account/settings/getAccount";
+import { getUserThirdwebClient } from "../../../../../api/lib/getAuthToken";
import { PublishedActions } from "../../../components/contract-actions-published.client";
import { DeployContractHeader } from "../../../components/contract-header";
-
function mapThirdwebPublisher(publisher: string) {
if (publisher === "thirdweb.eth") {
return "deployer.thirdweb.eth";
@@ -32,13 +31,14 @@ export default async function PublishedContractPage(
const params = await props.params;
// resolve ENS if required
let publisherAddress: string | undefined = undefined;
+ const client = await getUserThirdwebClient();
if (isAddress(params.publisher)) {
publisherAddress = params.publisher;
} else {
try {
publisherAddress = await resolveAddress({
- client: getThirdwebClient(),
+ client,
name: mapThirdwebPublisher(params.publisher),
});
} catch {
@@ -54,6 +54,7 @@ export default async function PublishedContractPage(
const publishedContractVersions = await fetchPublishedContractVersions(
publisherAddress,
params.contract_id,
+ client,
);
// determine the "active" version of the contract based on the version that is passed
@@ -73,6 +74,7 @@ export default async function PublishedContractPage(
{...params}
allVersions={publishedContractVersions}
activeVersion={publishedContract}
+ client={client}
>
moduleFromBase64(m)).filter((m) => m !== null) ||
[];
- return ;
+ const client = await getUserThirdwebClient();
+
+ return (
+
+ );
}
diff --git a/apps/dashboard/src/app/(dashboard)/published-contract/[publisher]/[contract_id]/layout.tsx b/apps/dashboard/src/app/(dashboard)/published-contract/[publisher]/[contract_id]/layout.tsx
index 476a9cae76d..6628a4fbcae 100644
--- a/apps/dashboard/src/app/(dashboard)/published-contract/[publisher]/[contract_id]/layout.tsx
+++ b/apps/dashboard/src/app/(dashboard)/published-contract/[publisher]/[contract_id]/layout.tsx
@@ -1,3 +1,4 @@
+import { getThirdwebClient } from "@/constants/thirdweb.server";
import { PublishedContractBreadcrumbs } from "./components/breadcrumbs.client";
import { getLatestPublishedContractsWithPublisherMapping } from "./utils/getPublishedContractsWithPublisherMapping";
@@ -23,6 +24,7 @@ export async function generateMetadata(props: { params: Promise }) {
await getLatestPublishedContractsWithPublisherMapping({
publisher: publisher,
contract_id: contract_id,
+ client: getThirdwebClient(undefined),
});
if (!publishedContract) {
diff --git a/apps/dashboard/src/app/(dashboard)/published-contract/[publisher]/[contract_id]/opengraph-image.tsx b/apps/dashboard/src/app/(dashboard)/published-contract/[publisher]/[contract_id]/opengraph-image.tsx
index 5828e050ded..645cd3d1752 100644
--- a/apps/dashboard/src/app/(dashboard)/published-contract/[publisher]/[contract_id]/opengraph-image.tsx
+++ b/apps/dashboard/src/app/(dashboard)/published-contract/[publisher]/[contract_id]/opengraph-image.tsx
@@ -19,16 +19,17 @@ export default async function Image(props: {
contract_id: string;
};
}) {
- const client = getThirdwebClient();
+ const client = getThirdwebClient(undefined);
const { publisher, contract_id } = props.params;
const [publishedContract, socialProfiles] = await Promise.all([
getLatestPublishedContractsWithPublisherMapping({
publisher: publisher,
contract_id: contract_id,
+ client,
}),
getSocialProfiles({
- address: (await resolveEns(publisher)).address || publisher,
+ address: (await resolveEns(publisher, client)).address || publisher,
client,
}),
]);
diff --git a/apps/dashboard/src/app/(dashboard)/published-contract/[publisher]/[contract_id]/page.tsx b/apps/dashboard/src/app/(dashboard)/published-contract/[publisher]/[contract_id]/page.tsx
index 61cc382ddeb..e7170ca754c 100644
--- a/apps/dashboard/src/app/(dashboard)/published-contract/[publisher]/[contract_id]/page.tsx
+++ b/apps/dashboard/src/app/(dashboard)/published-contract/[publisher]/[contract_id]/page.tsx
@@ -3,6 +3,7 @@ import { Separator } from "@/components/ui/separator";
import { notFound } from "next/navigation";
import { PublishedContract } from "../../../../../components/contract-components/published-contract";
import { getRawAccount } from "../../../../account/settings/getAccount";
+import { getUserThirdwebClient } from "../../../../api/lib/getAuthToken";
import { PublishedActions } from "../../components/contract-actions-published.client";
import { DeployContractHeader } from "../../components/contract-header";
import { getPublishedContractsWithPublisherMapping } from "./utils/getPublishedContractsWithPublisherMapping";
@@ -18,10 +19,12 @@ export default async function PublishedContractPage(
props: PublishedContractDeployPageProps,
) {
const params = await props.params;
+ const client = await getUserThirdwebClient();
const publishedContractVersions =
await getPublishedContractsWithPublisherMapping({
publisher: params.publisher,
contract_id: params.contract_id,
+ client,
});
if (!publishedContractVersions) {
@@ -42,6 +45,7 @@ export default async function PublishedContractPage(
{...params}
allVersions={publishedContractVersions}
activeVersion={publishedContract}
+ client={client}
>
res.arrayBuffer());
- const client = getThirdwebClient();
+ const client = getThirdwebClient(undefined);
const [
inter400,
diff --git a/apps/dashboard/src/app/(dashboard)/published-contract/components/contract-header.tsx b/apps/dashboard/src/app/(dashboard)/published-contract/components/contract-header.tsx
index 1c6ba08b8d4..46e48a75481 100644
--- a/apps/dashboard/src/app/(dashboard)/published-contract/components/contract-header.tsx
+++ b/apps/dashboard/src/app/(dashboard)/published-contract/components/contract-header.tsx
@@ -1,5 +1,6 @@
"use client";
import type { PropsWithChildren } from "react";
+import type { ThirdwebClient } from "thirdweb";
import type { PublishedContractWithVersion } from "../../../../components/contract-components/fetch-contracts-with-versions";
import { ModuleList } from "../[publisher]/[contract_id]/components/module-list.client";
import { DeployContractInfo } from "./contract-info";
@@ -11,6 +12,7 @@ type DeployContractHeaderProps = {
version?: string;
allVersions: PublishedContractWithVersion[];
activeVersion: PublishedContractWithVersion;
+ client: ThirdwebClient;
};
export function DeployContractHeader(
@@ -21,6 +23,7 @@ export function DeployContractHeader(
;
+ client: ThirdwebClient;
};
function mapThirdwebPublisher(publisher: string) {
@@ -25,7 +25,7 @@ function mapThirdwebPublisher(publisher: string) {
}
export async function DeployFormForPublishInfo(props: PublishBasedDeployProps) {
- const client = getThirdwebClient();
+ const client = props.client;
// resolve ENS if required
const publisherAddress = isAddress(props.publisher)
? props.publisher
@@ -36,9 +36,9 @@ export async function DeployFormForPublishInfo(props: PublishBasedDeployProps) {
// get all the published versions of the contract
const [publishedContractVersions, ...modules] = await Promise.all([
- fetchPublishedContractVersions(publisherAddress, props.contract_id),
+ fetchPublishedContractVersions(publisherAddress, props.contract_id, client),
...(props.modules || []).map((m) =>
- fetchPublishedContractVersion(m.publisher, m.moduleId, m.version),
+ fetchPublishedContractVersion(m.publisher, m.moduleId, client, m.version),
),
]);
diff --git a/apps/dashboard/src/app/(dashboard)/published-contract/page.tsx b/apps/dashboard/src/app/(dashboard)/published-contract/page.tsx
index 5a2bd8f5c87..960d5a3a7e5 100644
--- a/apps/dashboard/src/app/(dashboard)/published-contract/page.tsx
+++ b/apps/dashboard/src/app/(dashboard)/published-contract/page.tsx
@@ -1,6 +1,6 @@
-import { getThirdwebClient } from "@/constants/thirdweb.server";
import { redirect } from "next/navigation";
import { fetchDeployMetadata } from "thirdweb/contract";
+import { getUserThirdwebClient } from "../../api/lib/getAuthToken";
export default async function Page(props: {
searchParams: Promise<{
@@ -13,8 +13,10 @@ export default async function Page(props: {
return redirect("/team");
}
+ const client = await getUserThirdwebClient();
+
const contractMetadata = await fetchDeployMetadata({
- client: getThirdwebClient(),
+ client,
// force `ipfs://` prefix
uri: searchParams.uri.startsWith("ipfs://")
? searchParams.uri
diff --git a/apps/dashboard/src/app/account/components/AccountHeaderUI.stories.tsx b/apps/dashboard/src/app/account/components/AccountHeaderUI.stories.tsx
index c70976303d7..6dfb1dd3b43 100644
--- a/apps/dashboard/src/app/account/components/AccountHeaderUI.stories.tsx
+++ b/apps/dashboard/src/app/account/components/AccountHeaderUI.stories.tsx
@@ -1,9 +1,12 @@
import { Button } from "@/components/ui/button";
-import { getThirdwebClient } from "@/constants/thirdweb.server";
import type { Meta, StoryObj } from "@storybook/react";
import { ThirdwebProvider } from "thirdweb/react";
import { teamsAndProjectsStub } from "../../../stories/stubs";
-import { BadgeContainer, mobileViewport } from "../../../stories/utils";
+import {
+ BadgeContainer,
+ mobileViewport,
+ storybookThirdwebClient,
+} from "../../../stories/utils";
import {
AccountHeaderDesktopUI,
AccountHeaderMobileUI,
@@ -37,7 +40,6 @@ export const Mobile: Story = {
},
};
-const client = getThirdwebClient();
const accountAddressStub = "0x1F846F6DAE38E1C88D71EAA191760B15f38B7A37";
function Variants(props: {
@@ -61,7 +63,7 @@ function Variants(props: {
id: "foo",
email: "foo@example.com",
}}
- client={client}
+ client={storybookThirdwebClient}
getChangelogNotifications={() => Promise.resolve([])}
getInboxNotifications={() => Promise.resolve([])}
markNotificationAsRead={() => Promise.resolve()}
diff --git a/apps/dashboard/src/app/account/components/AccountHeaderUI.tsx b/apps/dashboard/src/app/account/components/AccountHeaderUI.tsx
index 4ad6d399241..edfa0c9c79b 100644
--- a/apps/dashboard/src/app/account/components/AccountHeaderUI.tsx
+++ b/apps/dashboard/src/app/account/components/AccountHeaderUI.tsx
@@ -117,6 +117,7 @@ export function AccountHeaderMobileUI(props: AccountHeaderCompProps) {
teamsAndProjects={props.teamsAndProjects}
upgradeTeamLink={undefined}
account={props.account}
+ client={props.client}
/>
)}
diff --git a/apps/dashboard/src/app/account/contracts/DeployedContractsPageHeader.tsx b/apps/dashboard/src/app/account/contracts/DeployedContractsPageHeader.tsx
index 30b7cdfd90f..dc124c26fcb 100644
--- a/apps/dashboard/src/app/account/contracts/DeployedContractsPageHeader.tsx
+++ b/apps/dashboard/src/app/account/contracts/DeployedContractsPageHeader.tsx
@@ -52,7 +52,6 @@ export function DeployedContractsPageHeader(props: {
href="/explore"
category="contracts"
label="deploy-contract"
- target="_blank"
>
Deploy contract
diff --git a/apps/dashboard/src/app/account/overview/AccountTeamsUI.stories.tsx b/apps/dashboard/src/app/account/overview/AccountTeamsUI.stories.tsx
index 997a9b5a27f..765168d4b39 100644
--- a/apps/dashboard/src/app/account/overview/AccountTeamsUI.stories.tsx
+++ b/apps/dashboard/src/app/account/overview/AccountTeamsUI.stories.tsx
@@ -1,7 +1,10 @@
-import { getThirdwebClient } from "@/constants/thirdweb.server";
import type { Meta, StoryObj } from "@storybook/react";
import { teamStub } from "../../../stories/stubs";
-import { BadgeContainer, mobileViewport } from "../../../stories/utils";
+import {
+ BadgeContainer,
+ mobileViewport,
+ storybookThirdwebClient,
+} from "../../../stories/utils";
import { AccountTeamsUI } from "./AccountTeamsUI";
const meta = {
@@ -37,7 +40,7 @@ function Variants() {
{
const member = await getMemberById(team.slug, account.id);
@@ -42,10 +47,7 @@ export default async function Page() {
);
diff --git a/apps/dashboard/src/app/account/settings/AccountSettingsPageUI.stories.tsx b/apps/dashboard/src/app/account/settings/AccountSettingsPageUI.stories.tsx
index ce46d76631c..1866df9c812 100644
--- a/apps/dashboard/src/app/account/settings/AccountSettingsPageUI.stories.tsx
+++ b/apps/dashboard/src/app/account/settings/AccountSettingsPageUI.stories.tsx
@@ -7,10 +7,12 @@ import {
SelectTrigger,
SelectValue,
} from "@/components/ui/select";
-import { getThirdwebClient } from "@/constants/thirdweb.server";
import type { Meta, StoryObj } from "@storybook/react";
import { useState } from "react";
-import { mobileViewport } from "../../../stories/utils";
+import {
+ mobileViewport,
+ storybookThirdwebClient,
+} from "../../../stories/utils";
import { AccountSettingsPageUI } from "./AccountSettingsPageUI";
const meta = {
@@ -41,8 +43,6 @@ export const Mobile: Story = {
},
};
-const client = getThirdwebClient();
-
function Variants() {
const [isVerifiedEmail, setIsVerifiedEmail] = useState(true);
const [sendEmailFails, setSendEmailFails] = useState(false);
@@ -119,7 +119,7 @@ function Variants() {
? new Date().toISOString()
: undefined,
}}
- client={client}
+ client={storybookThirdwebClient}
updateAccountAvatar={async () => {
await new Promise((resolve) => setTimeout(resolve, 1000));
}}
diff --git a/apps/dashboard/src/app/account/settings/page.tsx b/apps/dashboard/src/app/account/settings/page.tsx
index 26d76ce7173..31486fe5cd4 100644
--- a/apps/dashboard/src/app/account/settings/page.tsx
+++ b/apps/dashboard/src/app/account/settings/page.tsx
@@ -18,10 +18,15 @@ export default async function Page() {
loginRedirect(pagePath);
}
+ const client = getThirdwebClient({
+ jwt: token,
+ teamId: undefined,
+ });
+
return (
diff --git a/apps/dashboard/src/app/api/lib/getAuthToken.ts b/apps/dashboard/src/app/api/lib/getAuthToken.ts
index 6972a095d7d..6fc87f94507 100644
--- a/apps/dashboard/src/app/api/lib/getAuthToken.ts
+++ b/apps/dashboard/src/app/api/lib/getAuthToken.ts
@@ -1,5 +1,7 @@
import { COOKIE_ACTIVE_ACCOUNT, COOKIE_PREFIX_TOKEN } from "@/constants/cookie";
+import { getThirdwebClient } from "@/constants/thirdweb.server";
import { cookies } from "next/headers";
+import { LAST_USED_TEAM_ID } from "../../../constants/cookies";
export async function getAuthToken() {
const cookiesManager = await cookies();
@@ -26,3 +28,14 @@ export async function getAuthTokenWalletAddress() {
return null;
}
+
+export async function getUserThirdwebClient() {
+ const authToken = await getAuthToken();
+ const cookiesManager = await cookies();
+ const lastUsedTeamId = cookiesManager.get(LAST_USED_TEAM_ID)?.value;
+
+ return getThirdwebClient({
+ jwt: authToken,
+ teamId: lastUsedTeamId,
+ });
+}
diff --git a/apps/dashboard/src/app/drops/[slug]/opengraph-image.tsx b/apps/dashboard/src/app/drops/[slug]/opengraph-image.tsx
index 5176c666b3a..58522c1eb1e 100644
--- a/apps/dashboard/src/app/drops/[slug]/opengraph-image.tsx
+++ b/apps/dashboard/src/app/drops/[slug]/opengraph-image.tsx
@@ -81,9 +81,10 @@ export default async function Image({ params }: { params: { slug: string } }) {
),
// download the chain icon if there is one
chain.icon?.url && hasWorkingChainIcon
- ? download({ uri: chain.icon.url, client: getThirdwebClient() }).then(
- (res) => res.arrayBuffer(),
- )
+ ? download({
+ uri: chain.icon.url,
+ client: getThirdwebClient(undefined),
+ }).then((res) => res.arrayBuffer())
: undefined,
// download the background image (based on chain)
fetch(
diff --git a/apps/dashboard/src/app/drops/[slug]/page.tsx b/apps/dashboard/src/app/drops/[slug]/page.tsx
index 41d084d0cdd..9b569a4afd8 100644
--- a/apps/dashboard/src/app/drops/[slug]/page.tsx
+++ b/apps/dashboard/src/app/drops/[slug]/page.tsx
@@ -39,7 +39,7 @@ export default async function DropPage({
}
// eslint-disable-next-line no-restricted-syntax
const chain = defineDashboardChain(project.chainId, undefined);
- const client = getThirdwebClient();
+ const client = getThirdwebClient(undefined);
const contract = getContract({
address: project.contractAddress,
diff --git a/apps/dashboard/src/app/get-started/team/[team_slug]/layout.tsx b/apps/dashboard/src/app/get-started/team/[team_slug]/layout.tsx
index fc9ed44658b..b0dbc97de12 100644
--- a/apps/dashboard/src/app/get-started/team/[team_slug]/layout.tsx
+++ b/apps/dashboard/src/app/get-started/team/[team_slug]/layout.tsx
@@ -2,6 +2,7 @@ import { getProjects } from "@/api/projects";
import { getTeamBySlug, getTeams } from "@/api/team";
import { AppFooter } from "@/components/blocks/app-footer";
import { notFound } from "next/navigation";
+import { getThirdwebClient } from "../../../../@/constants/thirdweb.server";
import { getValidAccount } from "../../../account/settings/getAccount";
import {
getAuthToken,
@@ -42,10 +43,16 @@ export default async function Layout(props: {
})),
);
+ const client = getThirdwebClient({
+ jwt: authToken,
+ teamId: team.id,
+ });
+
return (
diff --git a/apps/dashboard/src/app/nebula-app/(app)/components/Chats.stories.tsx b/apps/dashboard/src/app/nebula-app/(app)/components/Chats.stories.tsx
index 5bff9807dee..3891e5c11c4 100644
--- a/apps/dashboard/src/app/nebula-app/(app)/components/Chats.stories.tsx
+++ b/apps/dashboard/src/app/nebula-app/(app)/components/Chats.stories.tsx
@@ -1,8 +1,10 @@
-import { getThirdwebClient } from "@/constants/thirdweb.server";
import type { Meta, StoryObj } from "@storybook/react";
import { ConnectButton, ThirdwebProvider } from "thirdweb/react";
import { randomLorem } from "../../../../stories/stubs";
-import { BadgeContainer } from "../../../../stories/utils";
+import {
+ BadgeContainer,
+ storybookThirdwebClient,
+} from "../../../../stories/utils";
import { type ChatMessage, Chats } from "./Chats";
const meta = {
@@ -135,7 +137,7 @@ function Story() {
-
+
{}}
- client={getThirdwebClient()}
+ client={storybookThirdwebClient}
authToken="xxxxx"
isChatStreaming={false}
sessionId="xxxxx"
@@ -218,7 +220,7 @@ function Story() {
{}}
- client={getThirdwebClient()}
+ client={storybookThirdwebClient}
authToken="xxxxx"
isChatStreaming={false}
sessionId="xxxxx"
@@ -249,7 +251,7 @@ function Variant(props: {
{}}
- client={getThirdwebClient()}
+ client={storybookThirdwebClient}
authToken="xxxxx"
isChatStreaming={false}
sessionId="xxxxx"
diff --git a/apps/dashboard/src/app/nebula-app/(app)/components/ExecuteTransactionCard.stories.tsx b/apps/dashboard/src/app/nebula-app/(app)/components/ExecuteTransactionCard.stories.tsx
index e7e8a350f06..be534a73a53 100644
--- a/apps/dashboard/src/app/nebula-app/(app)/components/ExecuteTransactionCard.stories.tsx
+++ b/apps/dashboard/src/app/nebula-app/(app)/components/ExecuteTransactionCard.stories.tsx
@@ -1,8 +1,10 @@
-import { getThirdwebClient } from "@/constants/thirdweb.server";
import type { Meta, StoryObj } from "@storybook/react";
import { useState } from "react";
import { ConnectButton, ThirdwebProvider } from "thirdweb/react";
-import { BadgeContainer } from "../../../../stories/utils";
+import {
+ BadgeContainer,
+ storybookThirdwebClient,
+} from "../../../../stories/utils";
import {
ExecuteTransactionCardLayout,
type TxStatus,
@@ -25,8 +27,6 @@ export const Variants: Story = {
args: {},
};
-const client = getThirdwebClient();
-
const exampleTxHash =
"0xbe81f5a6421625052214b41bb79d1d82751b29aa5639b54d120f00531bb8bcf";
@@ -35,7 +35,7 @@ function Story() {
-
+
@@ -66,7 +66,7 @@ function Variant(props: {
;
-const client = getThirdwebClient();
-
export const LoggedIn: Story = {
args: {
authToken: "foo",
nebulaParams: undefined,
label: "Ask AI about this contract",
examplePrompts: examplePrompts,
- client,
+ client: storybookThirdwebClient,
},
};
@@ -37,6 +35,6 @@ export const LoggedOut: Story = {
nebulaParams: undefined,
label: "Ask AI about this contract",
examplePrompts: examplePrompts,
- client,
+ client: storybookThirdwebClient,
},
};
diff --git a/apps/dashboard/src/app/project-showcase/[slug]/page.tsx b/apps/dashboard/src/app/project-showcase/[slug]/page.tsx
index 09a92a85e81..c130bb74636 100644
--- a/apps/dashboard/src/app/project-showcase/[slug]/page.tsx
+++ b/apps/dashboard/src/app/project-showcase/[slug]/page.tsx
@@ -77,7 +77,7 @@ export default async function DetailPage(props: {
src={
project.image?.startsWith("ipfs://")
? (resolveSchemeWithErrorHandler({
- client: getThirdwebClient(),
+ client: getThirdwebClient(undefined),
uri: project.image,
}) ?? "")
: (project.image ?? "/assets/showcase/default_image.png")
diff --git a/apps/dashboard/src/app/project-showcase/page.tsx b/apps/dashboard/src/app/project-showcase/page.tsx
index 63a31dbbb5c..5b88eaadd99 100644
--- a/apps/dashboard/src/app/project-showcase/page.tsx
+++ b/apps/dashboard/src/app/project-showcase/page.tsx
@@ -66,6 +66,8 @@ export default async function ProjectShowcasePage(props: {
currentPage * PROJECT_SHOWCASE_ITEMS_PER_PAGE,
);
+ const client = getThirdwebClient(undefined);
+
return (
@@ -137,7 +139,7 @@ export default async function ProjectShowcasePage(props: {
src={
project.image?.startsWith("ipfs://")
? (resolveSchemeWithErrorHandler({
- client: getThirdwebClient(),
+ client,
uri: project.image,
}) ?? "")
: (project.image ??
diff --git a/apps/dashboard/src/app/team/[team_slug]/(team)/layout.tsx b/apps/dashboard/src/app/team/[team_slug]/(team)/layout.tsx
index a60e7527c04..bc1a51fc6d4 100644
--- a/apps/dashboard/src/app/team/[team_slug]/(team)/layout.tsx
+++ b/apps/dashboard/src/app/team/[team_slug]/(team)/layout.tsx
@@ -2,10 +2,14 @@ import { getProjects } from "@/api/projects";
import { getTeams } from "@/api/team";
import { AppFooter } from "@/components/blocks/app-footer";
import { TabPathLinks } from "@/components/ui/tabs";
+import { getThirdwebClient } from "@/constants/thirdweb.server";
import { redirect } from "next/navigation";
import { AnnouncementBanner } from "../../../../components/notices/AnnouncementBanner";
import { getValidAccount } from "../../../account/settings/getAccount";
-import { getAuthTokenWalletAddress } from "../../../api/lib/getAuthToken";
+import {
+ getAuthToken,
+ getAuthTokenWalletAddress,
+} from "../../../api/lib/getAuthToken";
import { TeamHeaderLoggedIn } from "../../components/TeamHeader/team-header-logged-in.client";
export default async function TeamLayout(props: {
@@ -14,13 +18,14 @@ export default async function TeamLayout(props: {
}) {
const params = await props.params;
- const [accountAddress, account, teams] = await Promise.all([
+ const [accountAddress, account, teams, authToken] = await Promise.all([
getAuthTokenWalletAddress(),
getValidAccount(`/team/${params.team_slug}`),
getTeams(),
+ getAuthToken(),
]);
- if (!teams || !accountAddress) {
+ if (!teams || !accountAddress || !authToken) {
redirect("/login");
}
@@ -39,6 +44,11 @@ export default async function TeamLayout(props: {
})),
);
+ const client = getThirdwebClient({
+ jwt: authToken,
+ teamId: team.id,
+ });
+
return (
@@ -49,6 +59,7 @@ export default async function TeamLayout(props: {
currentProject={undefined}
account={account}
accountAddress={accountAddress}
+ client={client}
/>
diff --git a/apps/dashboard/src/app/team/[team_slug]/(team)/~/ecosystem/create/EcosystemCreatePage.tsx b/apps/dashboard/src/app/team/[team_slug]/(team)/~/ecosystem/create/EcosystemCreatePage.tsx
index d4813ff4820..55353817b9f 100644
--- a/apps/dashboard/src/app/team/[team_slug]/(team)/~/ecosystem/create/EcosystemCreatePage.tsx
+++ b/apps/dashboard/src/app/team/[team_slug]/(team)/~/ecosystem/create/EcosystemCreatePage.tsx
@@ -1,12 +1,18 @@
import { CreateEcosystemForm } from "./components/client/create-ecosystem-form.client";
import { EcosystemWalletPricingCard } from "./components/pricing-card";
-export async function EcosystemCreatePage(props: { teamSlug: string }) {
+export async function EcosystemCreatePage(props: {
+ teamSlug: string;
+ teamId: string;
+}) {
return (
-
+
diff --git a/apps/dashboard/src/app/team/[team_slug]/(team)/~/ecosystem/create/actions/create-ecosystem.ts b/apps/dashboard/src/app/team/[team_slug]/(team)/~/ecosystem/create/actions/create-ecosystem.ts
index e1ffebe2c9e..68c891e36af 100644
--- a/apps/dashboard/src/app/team/[team_slug]/(team)/~/ecosystem/create/actions/create-ecosystem.ts
+++ b/apps/dashboard/src/app/team/[team_slug]/(team)/~/ecosystem/create/actions/create-ecosystem.ts
@@ -8,6 +8,7 @@ import { getAuthToken } from "../../../../../../../api/lib/getAuthToken";
export async function createEcosystem(options: {
teamSlug: string;
+ teamId: string;
name: string;
logo: File;
permission: "PARTNER_WHITELIST" | "ANYONE";
@@ -19,10 +20,13 @@ export async function createEcosystem(options: {
};
}
- const { teamSlug, logo, ...data } = options;
+ const { teamSlug, teamId, logo, ...data } = options;
const imageUrl = await upload({
- client: getThirdwebClient(token),
+ client: getThirdwebClient({
+ jwt: token,
+ teamId: teamId,
+ }),
files: [logo],
});
diff --git a/apps/dashboard/src/app/team/[team_slug]/(team)/~/ecosystem/create/components/client/create-ecosystem-form.client.tsx b/apps/dashboard/src/app/team/[team_slug]/(team)/~/ecosystem/create/components/client/create-ecosystem-form.client.tsx
index e5b5dee22a1..32acacae3f3 100644
--- a/apps/dashboard/src/app/team/[team_slug]/(team)/~/ecosystem/create/components/client/create-ecosystem-form.client.tsx
+++ b/apps/dashboard/src/app/team/[team_slug]/(team)/~/ecosystem/create/components/client/create-ecosystem-form.client.tsx
@@ -41,7 +41,10 @@ const formSchema = z.object({
permission: z.union([z.literal("PARTNER_WHITELIST"), z.literal("ANYONE")]),
});
-export function CreateEcosystemForm(props: { teamSlug: string }) {
+export function CreateEcosystemForm(props: {
+ teamSlug: string;
+ teamId: string;
+}) {
const form = useForm
>({
resolver: zodResolver(formSchema),
defaultValues: {
@@ -56,6 +59,7 @@ export function CreateEcosystemForm(props: { teamSlug: string }) {
onSubmit={form.handleSubmit(async (values) => {
const res = await createEcosystem({
teamSlug: props.teamSlug,
+ teamId: props.teamId,
...values,
});
switch (res.status) {
diff --git a/apps/dashboard/src/app/team/[team_slug]/(team)/~/ecosystem/create/page.tsx b/apps/dashboard/src/app/team/[team_slug]/(team)/~/ecosystem/create/page.tsx
index 11fc8b6d1bc..0c52e6b8082 100644
--- a/apps/dashboard/src/app/team/[team_slug]/(team)/~/ecosystem/create/page.tsx
+++ b/apps/dashboard/src/app/team/[team_slug]/(team)/~/ecosystem/create/page.tsx
@@ -1,8 +1,16 @@
+import { getTeamBySlug } from "@/api/team";
+import { notFound } from "next/navigation";
import { EcosystemCreatePage } from "./EcosystemCreatePage";
export default async function Page(props: {
params: Promise<{ team_slug: string }>;
}) {
const { team_slug } = await props.params;
- return ;
+ const team = await getTeamBySlug(team_slug);
+
+ if (!team) {
+ return notFound();
+ }
+
+ return ;
}
diff --git a/apps/dashboard/src/app/team/[team_slug]/(team)/~/settings/general/GeneralSettingsPage.stories.tsx b/apps/dashboard/src/app/team/[team_slug]/(team)/~/settings/general/GeneralSettingsPage.stories.tsx
index 57a66fdd0df..60dc0574a4c 100644
--- a/apps/dashboard/src/app/team/[team_slug]/(team)/~/settings/general/GeneralSettingsPage.stories.tsx
+++ b/apps/dashboard/src/app/team/[team_slug]/(team)/~/settings/general/GeneralSettingsPage.stories.tsx
@@ -1,6 +1,6 @@
-import { getThirdwebClient } from "@/constants/thirdweb.server";
import type { Meta, StoryObj } from "@storybook/react";
import { teamStub } from "../../../../../../../stories/stubs";
+import { storybookThirdwebClient } from "../../../../../../../stories/utils";
import {
DeleteTeamCard,
LeaveTeamCard,
@@ -38,7 +38,7 @@ function Story() {
console.log(value);
await new Promise((resolve) => setTimeout(resolve, 1000));
}}
- client={getThirdwebClient()}
+ client={storybookThirdwebClient}
leaveTeam={async () => {
await new Promise((resolve) => setTimeout(resolve, 1000));
}}
diff --git a/apps/dashboard/src/app/team/[team_slug]/(team)/~/settings/general/Sidebar.stories.tsx b/apps/dashboard/src/app/team/[team_slug]/(team)/~/settings/general/Sidebar.stories.tsx
index 09069c91cc2..f7c8508af61 100644
--- a/apps/dashboard/src/app/team/[team_slug]/(team)/~/settings/general/Sidebar.stories.tsx
+++ b/apps/dashboard/src/app/team/[team_slug]/(team)/~/settings/general/Sidebar.stories.tsx
@@ -1,9 +1,9 @@
-import { getThirdwebClient } from "@/constants/thirdweb.server";
import type { Meta, StoryObj } from "@storybook/react";
import { teamStub } from "../../../../../../../stories/stubs";
import {
BadgeContainer,
mobileViewport,
+ storybookThirdwebClient,
} from "../../../../../../../stories/utils";
import { TeamSettingsSidebar } from "../_components/sidebar/TeamSettingsSidebar";
import { TeamSettingsMobileNav } from "../_components/sidebar/TeamsMobileNav";
@@ -36,8 +36,6 @@ export const Mobile: Story = {
},
};
-const client = getThirdwebClient();
-
function Story(props: {
type: "mobile" | "desktop";
}) {
@@ -51,7 +49,7 @@ function Story(props: {
account={{
id: "x",
}}
- client={client}
+ client={storybookThirdwebClient}
/>
@@ -59,7 +57,7 @@ function Story(props: {
diff --git a/apps/dashboard/src/app/team/[team_slug]/(team)/~/settings/members/ManageInvitesSection.stories.tsx b/apps/dashboard/src/app/team/[team_slug]/(team)/~/settings/members/ManageInvitesSection.stories.tsx
index 1a9590de416..7b63e31ef36 100644
--- a/apps/dashboard/src/app/team/[team_slug]/(team)/~/settings/members/ManageInvitesSection.stories.tsx
+++ b/apps/dashboard/src/app/team/[team_slug]/(team)/~/settings/members/ManageInvitesSection.stories.tsx
@@ -1,9 +1,11 @@
import type { TeamInvite } from "@/api/team-invites";
import type { TeamAccountRole } from "@/api/team-members";
-import { getThirdwebClient } from "@/constants/thirdweb.server";
import type { Meta, StoryObj } from "@storybook/react";
import { teamStub } from "../../../../../../../stories/stubs";
-import { BadgeContainer } from "../../../../../../../stories/utils";
+import {
+ BadgeContainer,
+ storybookThirdwebClient,
+} from "../../../../../../../stories/utils";
import { ManageInvitesSection } from "./ManageInvitesSection";
const meta = {
@@ -70,7 +72,7 @@ function Story() {
team={freeTeam}
userHasEditPermission={true}
teamInvites={invitesStub}
- client={getThirdwebClient()}
+ client={storybookThirdwebClient}
deleteInvite={deleteInviteStub}
/>
@@ -80,7 +82,7 @@ function Story() {
team={freeTeam}
userHasEditPermission={false}
teamInvites={invitesStub}
- client={getThirdwebClient()}
+ client={storybookThirdwebClient}
deleteInvite={deleteInviteStub}
/>
diff --git a/apps/dashboard/src/app/team/[team_slug]/(team)/~/settings/members/TeamMembersSettingsPage.stories.tsx b/apps/dashboard/src/app/team/[team_slug]/(team)/~/settings/members/TeamMembersSettingsPage.stories.tsx
index 2125b15383f..d8d7defa591 100644
--- a/apps/dashboard/src/app/team/[team_slug]/(team)/~/settings/members/TeamMembersSettingsPage.stories.tsx
+++ b/apps/dashboard/src/app/team/[team_slug]/(team)/~/settings/members/TeamMembersSettingsPage.stories.tsx
@@ -1,8 +1,10 @@
import type { TeamAccountRole, TeamMember } from "@/api/team-members";
-import { getThirdwebClient } from "@/constants/thirdweb.server";
import type { Meta, StoryObj } from "@storybook/react";
import { teamStub } from "../../../../../../../stories/stubs";
-import { BadgeContainer } from "../../../../../../../stories/utils";
+import {
+ BadgeContainer,
+ storybookThirdwebClient,
+} from "../../../../../../../stories/utils";
import { ManageMembersSection } from "./ManageMembersSection";
const meta = {
@@ -77,7 +79,7 @@ function Story() {
team={freeTeam}
userHasEditPermission={true}
members={membersStub}
- client={getThirdwebClient()}
+ client={storybookThirdwebClient}
deleteMember={deleteMemberStub}
/>
@@ -87,7 +89,7 @@ function Story() {
team={freeTeam}
userHasEditPermission={false}
members={membersStub}
- client={getThirdwebClient()}
+ client={storybookThirdwebClient}
deleteMember={deleteMemberStub}
/>
@@ -97,7 +99,7 @@ function Story() {
team={freeTeam}
userHasEditPermission={true}
members={membersStubNoName}
- client={getThirdwebClient()}
+ client={storybookThirdwebClient}
deleteMember={deleteMemberStub}
/>
diff --git a/apps/dashboard/src/app/team/[team_slug]/(team)/~/settings/members/page.tsx b/apps/dashboard/src/app/team/[team_slug]/(team)/~/settings/members/page.tsx
index c394777aa40..b5f06a3c9e1 100644
--- a/apps/dashboard/src/app/team/[team_slug]/(team)/~/settings/members/page.tsx
+++ b/apps/dashboard/src/app/team/[team_slug]/(team)/~/settings/members/page.tsx
@@ -50,12 +50,17 @@ export default async function Page(props: {
(invite) => invite.status === "pending" || invite.status === "expired",
);
+ const client = getThirdwebClient({
+ jwt: authToken,
+ teamId: team.id,
+ });
+
return (
);
diff --git a/apps/dashboard/src/app/team/[team_slug]/(team)/~/settings/page.tsx b/apps/dashboard/src/app/team/[team_slug]/(team)/~/settings/page.tsx
index f4a4a2f07d9..9d66c2d3cd7 100644
--- a/apps/dashboard/src/app/team/[team_slug]/(team)/~/settings/page.tsx
+++ b/apps/dashboard/src/app/team/[team_slug]/(team)/~/settings/page.tsx
@@ -22,10 +22,15 @@ export default async function Page(props: {
notFound();
}
+ const client = getThirdwebClient({
+ jwt: token,
+ teamId: team.id,
+ });
+
return (
);
diff --git a/apps/dashboard/src/app/team/[team_slug]/(team)/~/usage/overview/components/SponsoredTransactionsTableUI.stories.tsx b/apps/dashboard/src/app/team/[team_slug]/(team)/~/usage/overview/components/SponsoredTransactionsTableUI.stories.tsx
index fab4244d957..a2e0d17ef33 100644
--- a/apps/dashboard/src/app/team/[team_slug]/(team)/~/usage/overview/components/SponsoredTransactionsTableUI.stories.tsx
+++ b/apps/dashboard/src/app/team/[team_slug]/(team)/~/usage/overview/components/SponsoredTransactionsTableUI.stories.tsx
@@ -1,10 +1,10 @@
import { Label } from "@/components/ui/label";
import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group";
-import { getThirdwebClient } from "@/constants/thirdweb.server";
import type { Meta, StoryObj } from "@storybook/react";
import { useState } from "react";
import { ThirdwebProvider } from "thirdweb/react";
import { projectStub } from "../../../../../../../../stories/stubs";
+import { storybookThirdwebClient } from "../../../../../../../../stories/utils";
import {
type SponsoredTransaction,
SponsoredTransactionsTableUI,
@@ -64,8 +64,6 @@ function createSponsoredTransactionStub() {
} satisfies SponsoredTransaction;
}
-const client = getThirdwebClient();
-
export const Default: Story = {
args: {
totalPages: 4,
@@ -157,7 +155,7 @@ function Variant(props: {
filters={{}}
setFilters={() => {}}
isError={props.isError}
- client={client}
+ client={storybookThirdwebClient}
totalPages={props.totalPages}
isPending={props.isPending}
pageNumber={pageNumber}
diff --git a/apps/dashboard/src/app/team/[team_slug]/(team)/~/usage/page.tsx b/apps/dashboard/src/app/team/[team_slug]/(team)/~/usage/page.tsx
index 11ea58441fe..84c54d049e3 100644
--- a/apps/dashboard/src/app/team/[team_slug]/(team)/~/usage/page.tsx
+++ b/apps/dashboard/src/app/team/[team_slug]/(team)/~/usage/page.tsx
@@ -56,7 +56,10 @@ export default async function Page(props: {
);
}
- const client = getThirdwebClient(authToken);
+ const client = getThirdwebClient({
+ jwt: authToken,
+ teamId: team.id,
+ });
return (
{
try {
- localStorage.setItem(LAST_USED_PROJECT_ID, props.projectId);
- localStorage.setItem(LAST_USED_TEAM_ID, props.teamId);
+ setCookie(LAST_USED_PROJECT_ID, props.projectId);
+ setCookie(LAST_USED_TEAM_ID, props.teamId);
} catch {
// ignore localStorage errors
}
diff --git a/apps/dashboard/src/app/team/[team_slug]/[project_slug]/components/Transactions/TransactionCharts.tsx b/apps/dashboard/src/app/team/[team_slug]/[project_slug]/components/Transactions/TransactionCharts.tsx
index ac8f2cdee70..f00da815aef 100644
--- a/apps/dashboard/src/app/team/[team_slug]/[project_slug]/components/Transactions/TransactionCharts.tsx
+++ b/apps/dashboard/src/app/team/[team_slug]/[project_slug]/components/Transactions/TransactionCharts.tsx
@@ -1,7 +1,6 @@
-import { defineChain, getContract } from "thirdweb";
+import { type ThirdwebClient, defineChain, getContract } from "thirdweb";
import { getChainMetadata } from "thirdweb/chains";
import { TransactionsChartCardUI } from "../../../(team)/_components/TransactionsCard";
-import { getThirdwebClient } from "../../../../../../@/constants/thirdweb.server";
import { fetchDashboardContractMetadata } from "../../../../../../@3rdweb-sdk/react/hooks/useDashboardContractMetadata";
import type { TransactionStats } from "../../../../../../types/analytics";
import { PieChartCard } from "../../../../components/Analytics/PieChartCard";
@@ -10,10 +9,12 @@ export function TransactionsChartsUI({
data,
aggregatedData,
searchParams,
+ client,
}: {
data: TransactionStats[];
aggregatedData: TransactionStats[];
searchParams: { [key: string]: string | string[] | undefined };
+ client: ThirdwebClient;
}) {
return (
<>
@@ -25,7 +26,7 @@ export function TransactionsChartsUI({
/>
-
+
>
);
@@ -65,7 +66,8 @@ async function ChainDistributionCard({ data }: { data: TransactionStats[] }) {
async function ContractDistributionCard({
data,
-}: { data: TransactionStats[] }) {
+ client,
+}: { data: TransactionStats[]; client: ThirdwebClient }) {
const _reducedData = await Promise.all(
Object.entries(
data
@@ -97,7 +99,7 @@ async function ContractDistributionCard({
getContract({
chain,
address: contractAddress as string, // we filter above
- client: getThirdwebClient(),
+ client,
}),
).catch(() => undefined);
return {
diff --git a/apps/dashboard/src/app/team/[team_slug]/[project_slug]/components/Transactions/index.tsx b/apps/dashboard/src/app/team/[team_slug]/[project_slug]/components/Transactions/index.tsx
index bd6d0379ecd..002c9cd7e65 100644
--- a/apps/dashboard/src/app/team/[team_slug]/[project_slug]/components/Transactions/index.tsx
+++ b/apps/dashboard/src/app/team/[team_slug]/[project_slug]/components/Transactions/index.tsx
@@ -1,5 +1,6 @@
import { LoadingChartState } from "components/analytics/empty-chart-state";
import { Suspense } from "react";
+import type { ThirdwebClient } from "thirdweb";
import type { AnalyticsQueryParams } from "types/analytics";
import { getClientTransactions } from "../../../../../../@/api/analytics";
import { TransactionsChartsUI } from "./TransactionCharts";
@@ -7,6 +8,7 @@ import { TransactionsChartsUI } from "./TransactionCharts";
export function TransactionsCharts(
props: AnalyticsQueryParams & {
searchParams: { [key: string]: string | string[] | undefined };
+ client: ThirdwebClient;
},
) {
return (
@@ -26,6 +28,7 @@ export function TransactionsCharts(
async function TransactionsChartCardAsync(
props: AnalyticsQueryParams & {
searchParams: { [key: string]: string | string[] | undefined };
+ client: ThirdwebClient;
},
) {
const [data, aggregatedData] = await Promise.all([
@@ -45,6 +48,7 @@ async function TransactionsChartCardAsync(
data={data}
aggregatedData={aggregatedData}
searchParams={props.searchParams}
+ client={props.client}
/>
);
}
diff --git a/apps/dashboard/src/app/team/[team_slug]/[project_slug]/connect/account-abstraction/factories/page.tsx b/apps/dashboard/src/app/team/[team_slug]/[project_slug]/connect/account-abstraction/factories/page.tsx
index 698b2738a62..065cda369ce 100644
--- a/apps/dashboard/src/app/team/[team_slug]/[project_slug]/connect/account-abstraction/factories/page.tsx
+++ b/apps/dashboard/src/app/team/[team_slug]/[project_slug]/connect/account-abstraction/factories/page.tsx
@@ -115,7 +115,10 @@ async function AsyncYourFactories(props: {
authToken: props.authToken,
});
- const client = getThirdwebClient(props.authToken);
+ const client = getThirdwebClient({
+ jwt: props.authToken,
+ teamId: props.teamId,
+ });
const factories = (
await Promise.all(
diff --git a/apps/dashboard/src/app/team/[team_slug]/[project_slug]/connect/account-abstraction/page.tsx b/apps/dashboard/src/app/team/[team_slug]/[project_slug]/connect/account-abstraction/page.tsx
index bb660eddb46..abc7522738b 100644
--- a/apps/dashboard/src/app/team/[team_slug]/[project_slug]/connect/account-abstraction/page.tsx
+++ b/apps/dashboard/src/app/team/[team_slug]/[project_slug]/connect/account-abstraction/page.tsx
@@ -69,6 +69,11 @@ export default async function Page(props: {
period: interval,
});
+ const client = getThirdwebClient({
+ jwt: authToken,
+ teamId: project.teamId,
+ });
+
return (
;
}) {
const params = await props.params;
- const [accountAddress, teams, account] = await Promise.all([
+ const [accountAddress, teams, account, authToken] = await Promise.all([
getAuthTokenWalletAddress(),
getTeams(),
getValidAccount(`/team/${params.team_slug}/${params.project_slug}`),
+ getAuthToken(),
]);
- if (!teams || !accountAddress) {
+ if (!teams || !accountAddress || !authToken) {
redirect("/login");
}
@@ -50,6 +55,10 @@ export default async function ProjectLayout(props: {
}
const layoutPath = `/team/${params.team_slug}/${params.project_slug}`;
+ const client = getThirdwebClient({
+ jwt: authToken,
+ teamId: team.id,
+ });
return (
@@ -62,6 +71,7 @@ export default async function ProjectLayout(props: {
teamsAndProjects={teamsAndProjects}
account={account}
accountAddress={accountAddress}
+ client={client}
/>
diff --git a/apps/dashboard/src/app/team/[team_slug]/[project_slug]/page.tsx b/apps/dashboard/src/app/team/[team_slug]/[project_slug]/page.tsx
index 78dc7d4be97..e37650f24c3 100644
--- a/apps/dashboard/src/app/team/[team_slug]/[project_slug]/page.tsx
+++ b/apps/dashboard/src/app/team/[team_slug]/[project_slug]/page.tsx
@@ -22,21 +22,24 @@ import {
isProjectActive,
} from "@/api/analytics";
import { EmptyStateCard } from "app/team/components/Analytics/EmptyStateCard";
+import { RangeSelector } from "components/analytics/range-selector";
import { Suspense } from "react";
+import type { ThirdwebClient } from "thirdweb";
import {
type ChainMetadata,
defineChain,
getChainMetadata,
} from "thirdweb/chains";
import { type WalletId, getWalletInfo } from "thirdweb/wallets";
+import { getThirdwebClient } from "../../../../@/constants/thirdweb.server";
+import { getAuthToken } from "../../../api/lib/getAuthToken";
+import { loginRedirect } from "../../../login/loginRedirect";
import { CombinedBarChartCard } from "../../components/Analytics/CombinedBarChartCard";
import { PieChartCard } from "../../components/Analytics/PieChartCard";
import { ProjectFTUX } from "./components/ProjectFTUX/ProjectFTUX";
import { RpcMethodBarChartCard } from "./components/RpcMethodBarChartCard";
import { TransactionsCharts } from "./components/Transactions";
-import { RangeSelector } from "components/analytics/range-selector";
-
interface PageParams {
team_slug: string;
project_slug: string;
@@ -57,7 +60,14 @@ export default async function ProjectOverviewPage(props: PageProps) {
props.searchParams,
]);
- const project = await getProject(params.team_slug, params.project_slug);
+ const [authToken, project] = await Promise.all([
+ getAuthToken(),
+ getProject(params.team_slug, params.project_slug),
+ ]);
+
+ if (!authToken) {
+ loginRedirect(`/team/${params.team_slug}`);
+ }
if (!project) {
redirect(`/team/${params.team_slug}`);
@@ -78,6 +88,11 @@ export default async function ProjectOverviewPage(props: PageProps) {
const isActive = Object.values(activeStatus).some((v) => !!v);
+ const client = getThirdwebClient({
+ jwt: authToken,
+ teamId: project.teamId,
+ });
+
return (
@@ -105,6 +120,7 @@ export default async function ProjectOverviewPage(props: PageProps) {
range={range}
interval={interval}
searchParams={searchParams}
+ client={client}
/>
@@ -120,8 +136,9 @@ async function ProjectAnalytics(props: {
range: Range;
interval: "day" | "week";
searchParams: PageSearchParams;
+ client: ThirdwebClient;
}) {
- const { project, range, interval, searchParams } = props;
+ const { project, range, interval, searchParams, client } = props;
// Fetch all analytics data in parallel
const [
@@ -221,6 +238,7 @@ async function ProjectAnalytics(props: {
to={range.to}
period={interval}
teamId={project.teamId}
+ client={client}
/>
{userOpUsageTimeSeries.status === "fulfilled" &&
userOpUsage.status === "fulfilled" &&
diff --git a/apps/dashboard/src/app/team/[team_slug]/[project_slug]/settings/ProjectGeneralSettingsPage.stories.tsx b/apps/dashboard/src/app/team/[team_slug]/[project_slug]/settings/ProjectGeneralSettingsPage.stories.tsx
index 11e36cb09d4..9304ae7158f 100644
--- a/apps/dashboard/src/app/team/[team_slug]/[project_slug]/settings/ProjectGeneralSettingsPage.stories.tsx
+++ b/apps/dashboard/src/app/team/[team_slug]/[project_slug]/settings/ProjectGeneralSettingsPage.stories.tsx
@@ -1,6 +1,6 @@
-import { getThirdwebClient } from "@/constants/thirdweb.server";
import type { Meta, StoryObj } from "@storybook/react";
import { projectStub, teamStub } from "../../../../../stories/stubs";
+import { storybookThirdwebClient } from "../../../../../stories/utils";
import { ProjectGeneralSettingsPageUI } from "./ProjectGeneralSettingsPage";
const meta = {
@@ -44,7 +44,7 @@ function Story(props: {
await new Promise((resolve) => setTimeout(resolve, 1000));
console.log("transferProject", newTeam);
}}
- client={getThirdwebClient()}
+ client={storybookThirdwebClient}
teamsWithRole={[
{
role: props.isOwnerAccount ? "OWNER" : "MEMBER",
diff --git a/apps/dashboard/src/app/team/[team_slug]/[project_slug]/settings/page.tsx b/apps/dashboard/src/app/team/[team_slug]/[project_slug]/settings/page.tsx
index 744075c97ac..0d42146d2d6 100644
--- a/apps/dashboard/src/app/team/[team_slug]/[project_slug]/settings/page.tsx
+++ b/apps/dashboard/src/app/team/[team_slug]/[project_slug]/settings/page.tsx
@@ -50,6 +50,11 @@ export default async function Page(props: {
}),
);
+ const client = getThirdwebClient({
+ jwt: authToken,
+ teamId: currentTeam.id,
+ });
+
const currentTeamWithRole = teamsWithRole.find(
(teamWithRole) => teamWithRole.team.id === currentTeam.id,
);
@@ -61,7 +66,7 @@ export default async function Page(props: {
project={project}
teamSlug={team_slug}
showNebulaSettings={currentTeam.enabledScopes.includes("nebula")}
- client={getThirdwebClient(authToken)}
+ client={client}
teamId={currentTeam.id}
teamsWithRole={teamsWithRole}
isOwnerAccount={isOwnerAccount}
diff --git a/apps/dashboard/src/app/team/[team_slug]/layout.tsx b/apps/dashboard/src/app/team/[team_slug]/layout.tsx
index 16577a91c50..df8e0a9f3b6 100644
--- a/apps/dashboard/src/app/team/[team_slug]/layout.tsx
+++ b/apps/dashboard/src/app/team/[team_slug]/layout.tsx
@@ -40,7 +40,7 @@ export default async function RootTeamLayout(props: {
{props.children}
-
+
diff --git a/apps/dashboard/src/app/team/components/TeamHeader/TeamHeaderUI.stories.tsx b/apps/dashboard/src/app/team/components/TeamHeader/TeamHeaderUI.stories.tsx
index 0e33470299a..0cc14c2a4ca 100644
--- a/apps/dashboard/src/app/team/components/TeamHeader/TeamHeaderUI.stories.tsx
+++ b/apps/dashboard/src/app/team/components/TeamHeader/TeamHeaderUI.stories.tsx
@@ -1,11 +1,14 @@
import type { Project } from "@/api/projects";
import type { Team } from "@/api/team";
import { Button } from "@/components/ui/button";
-import { getThirdwebClient } from "@/constants/thirdweb.server";
import type { Meta, StoryObj } from "@storybook/react";
import { ThirdwebProvider } from "thirdweb/react";
import { teamsAndProjectsStub } from "../../../../stories/stubs";
-import { BadgeContainer, mobileViewport } from "../../../../stories/utils";
+import {
+ BadgeContainer,
+ mobileViewport,
+ storybookThirdwebClient,
+} from "../../../../stories/utils";
import { TeamHeaderDesktopUI, TeamHeaderMobileUI } from "./TeamHeaderUI";
const meta = {
@@ -36,8 +39,6 @@ export const Mobile: Story = {
},
};
-const client = getThirdwebClient();
-
function Variants(props: {
type: "mobile" | "desktop";
}) {
@@ -164,7 +165,7 @@ function Variant(props: {
logout={() => {}}
connectButton={}
createProject={() => {}}
- client={client}
+ client={storybookThirdwebClient}
getChangelogNotifications={getChangelogsStub}
getInboxNotifications={getInboxNotificationsStub}
markNotificationAsRead={markNotificationAsReadStub}
diff --git a/apps/dashboard/src/app/team/components/TeamHeader/TeamHeaderUI.tsx b/apps/dashboard/src/app/team/components/TeamHeader/TeamHeaderUI.tsx
index 57650caf0d4..b38b9bc8aba 100644
--- a/apps/dashboard/src/app/team/components/TeamHeader/TeamHeaderUI.tsx
+++ b/apps/dashboard/src/app/team/components/TeamHeader/TeamHeaderUI.tsx
@@ -165,6 +165,7 @@ export function TeamHeaderMobileUI(props: TeamHeaderCompProps) {
teamsAndProjects={props.teamsAndProjects}
upgradeTeamLink={`/team/${currentTeam.slug}/settings`}
account={props.account}
+ client={props.client}
/>
diff --git a/apps/dashboard/src/app/team/components/TeamHeader/TeamSelectorMobileMenuButton.tsx b/apps/dashboard/src/app/team/components/TeamHeader/TeamSelectorMobileMenuButton.tsx
index a94849ed37b..db8431e763a 100644
--- a/apps/dashboard/src/app/team/components/TeamHeader/TeamSelectorMobileMenuButton.tsx
+++ b/apps/dashboard/src/app/team/components/TeamHeader/TeamSelectorMobileMenuButton.tsx
@@ -5,9 +5,9 @@ import type { Team } from "@/api/team";
import { DynamicHeight } from "@/components/ui/DynamicHeight";
import { Button } from "@/components/ui/button";
import { Dialog, DialogContent, DialogTrigger } from "@/components/ui/dialog";
-import { getThirdwebClient } from "@/constants/thirdweb.server";
import type { Account } from "@3rdweb-sdk/react/hooks/useApi";
import { ChevronsUpDownIcon } from "lucide-react";
+import type { ThirdwebClient } from "thirdweb";
import { TeamSelectionUI } from "./TeamSelectionUI";
type TeamSelectorMobileMenuButtonProps = {
@@ -15,10 +15,9 @@ type TeamSelectorMobileMenuButtonProps = {
teamsAndProjects: Array<{ team: Team; projects: Project[] }>;
upgradeTeamLink: string | undefined;
account: Pick | undefined;
+ client: ThirdwebClient;
};
-const client = getThirdwebClient();
-
export function TeamSelectorMobileMenuButton(
props: TeamSelectorMobileMenuButtonProps,
) {
@@ -49,7 +48,7 @@ export function TeamSelectorMobileMenuButton(
teamsAndProjects={teamsAndProjects}
upgradeTeamLink={props.upgradeTeamLink}
account={props.account}
- client={client}
+ client={props.client}
/>
diff --git a/apps/dashboard/src/app/team/components/TeamHeader/team-header-logged-in.client.tsx b/apps/dashboard/src/app/team/components/TeamHeader/team-header-logged-in.client.tsx
index 24472c44080..8ab5776f172 100644
--- a/apps/dashboard/src/app/team/components/TeamHeader/team-header-logged-in.client.tsx
+++ b/apps/dashboard/src/app/team/components/TeamHeader/team-header-logged-in.client.tsx
@@ -2,11 +2,11 @@
import type { Project } from "@/api/projects";
import type { Team } from "@/api/team";
-import { getThirdwebClient } from "@/constants/thirdweb.server";
import { useDashboardRouter } from "@/lib/DashboardRouter";
import { CustomConnectWallet } from "@3rdweb-sdk/react/components/connect-wallet";
import type { Account } from "@3rdweb-sdk/react/hooks/useApi";
import { useCallback, useState } from "react";
+import type { ThirdwebClient } from "thirdweb";
import { useActiveWallet, useDisconnect } from "thirdweb/react";
import { LazyCreateProjectDialog } from "../../../../components/settings/ApiKeys/Create/LazyCreateAPIKeyDialog";
import { doLogout } from "../../../login/auth-actions";
@@ -27,6 +27,7 @@ export function TeamHeaderLoggedIn(props: {
currentProject: Project | undefined;
account: Pick;
accountAddress: string;
+ client: ThirdwebClient;
}) {
const [createProjectDialogState, setCreateProjectDialogState] = useState<
{ team: Team; isOpen: true } | { isOpen: false }
@@ -61,7 +62,7 @@ export function TeamHeaderLoggedIn(props: {
team,
});
},
- client: getThirdwebClient(),
+ client: props.client,
accountAddress: props.accountAddress,
getChangelogNotifications: getChangelogNotifications,
getInboxNotifications: getInboxNotifications,
diff --git a/apps/dashboard/src/app/team/components/TeamHeader/team-header.tsx b/apps/dashboard/src/app/team/components/TeamHeader/team-header.tsx
index 08b6b42a978..e9dd3cfbad1 100644
--- a/apps/dashboard/src/app/team/components/TeamHeader/team-header.tsx
+++ b/apps/dashboard/src/app/team/components/TeamHeader/team-header.tsx
@@ -1,21 +1,32 @@
import { getProjects } from "@/api/projects";
import { getTeams } from "@/api/team";
+import { cookies } from "next/headers";
+import { getThirdwebClient } from "../../../../@/constants/thirdweb.server";
+import { LAST_USED_TEAM_ID } from "../../../../constants/cookies";
import { getRawAccount } from "../../../account/settings/getAccount";
-import { getAuthTokenWalletAddress } from "../../../api/lib/getAuthToken";
+import {
+ getAuthToken,
+ getAuthTokenWalletAddress,
+} from "../../../api/lib/getAuthToken";
import { HeaderLoggedOut } from "../HeaderLoggedOut/HeaderLoggedOut";
import { TeamHeaderLoggedIn } from "./team-header-logged-in.client";
export async function TeamHeader() {
- const [account, teams, accountAddress] = await Promise.all([
+ const [account, teams, accountAddress, authToken] = await Promise.all([
getRawAccount(),
getTeams(),
getAuthTokenWalletAddress(),
+ getAuthToken(),
]);
if (!account || !accountAddress || !teams) {
return ;
}
+ const cookiesObj = await cookies();
+ const lastUsedTeamId = cookiesObj.get(LAST_USED_TEAM_ID)?.value;
+ const lastUsedTeam = teams.find((team) => team.id === lastUsedTeamId);
+
const teamsAndProjects = await Promise.all(
teams.map(async (team) => ({
team,
@@ -24,13 +35,21 @@ export async function TeamHeader() {
);
const firstTeam = teams[0];
- if (!firstTeam) {
+ const selectedTeam = lastUsedTeam || firstTeam;
+
+ if (!selectedTeam) {
return ;
}
+ const client = getThirdwebClient({
+ jwt: authToken,
+ teamId: lastUsedTeam?.id,
+ });
+
return (
{
setCookie(LAST_VISITED_TEAM_PAGE_PATH, pathname);
- }, [pathname]);
+ setCookie(LAST_USED_TEAM_ID, props.teamId);
+ }, [pathname, props.teamId]);
return null;
}
diff --git a/apps/dashboard/src/components/buttons/TransactionButton.stories.tsx b/apps/dashboard/src/components/buttons/TransactionButton.stories.tsx
index de62eb1d7d1..e7061d8ba53 100644
--- a/apps/dashboard/src/components/buttons/TransactionButton.stories.tsx
+++ b/apps/dashboard/src/components/buttons/TransactionButton.stories.tsx
@@ -8,13 +8,12 @@ import {
SelectValue,
} from "@/components/ui/select";
import { Switch } from "@/components/ui/switch";
-import { getThirdwebClient } from "@/constants/thirdweb.server";
import type { Meta, StoryObj } from "@storybook/react";
import { useMutation } from "@tanstack/react-query";
import { StarIcon } from "lucide-react";
import { useState } from "react";
import { ConnectButton, ThirdwebProvider } from "thirdweb/react";
-import { BadgeContainer } from "../../stories/utils";
+import { BadgeContainer, storybookThirdwebClient } from "../../stories/utils";
import { TransactionButton } from "./TransactionButton";
const meta = {
@@ -79,7 +78,7 @@ function Story() {
-
+
= ({
prefillSlug,
prefillChainId,
}) => {
+ const client = useThirdwebClient();
const { idToChain, nameToChain } = useAllChainsData();
const chainOverrides = useStore(chainOverridesStore);
@@ -67,7 +69,11 @@ export const ConfigureNetworkForm: React.FC = ({
: // if chain is custom or modified, show the rpc as is
editingChain.isCustom || editingChain.isModified
? editingChain.rpc[0]
- : getDashboardChainRpc(editingChain.chainId, editingChain)) || "",
+ : getDashboardChainRpc(
+ editingChain.chainId,
+ editingChain,
+ client,
+ )) || "",
chainId: editingChain?.chainId
? `${editingChain?.chainId}`
: prefillChainId || "",
diff --git a/apps/dashboard/src/components/contract-components/contract-deploy-form/add-to-project-card.stories.tsx b/apps/dashboard/src/components/contract-components/contract-deploy-form/add-to-project-card.stories.tsx
index a3cd330fd5b..563ba08f1a3 100644
--- a/apps/dashboard/src/components/contract-components/contract-deploy-form/add-to-project-card.stories.tsx
+++ b/apps/dashboard/src/components/contract-components/contract-deploy-form/add-to-project-card.stories.tsx
@@ -1,7 +1,9 @@
-import { getThirdwebClient } from "@/constants/thirdweb.server";
import type { Meta, StoryObj } from "@storybook/react";
import { useState } from "react";
-import { BadgeContainer } from "../../../stories/utils";
+import {
+ BadgeContainer,
+ storybookThirdwebClient,
+} from "../../../stories/utils";
import {
AddToProjectCardUI,
type MinimalProject,
@@ -83,7 +85,7 @@ function Variant(props: {
= ({
};
try {
- const lastUsedTeamSlug = localStorage.getItem(LAST_USED_TEAM_ID);
- const lastUsedProjectSlug = localStorage.getItem(LAST_USED_PROJECT_ID);
+ const lastUsedTeamSlug = getCookie(LAST_USED_TEAM_ID);
+ const lastUsedProjectSlug = getCookie(LAST_USED_PROJECT_ID);
if (!lastUsedTeamSlug || !lastUsedProjectSlug) {
return defaultSelection;
diff --git a/apps/dashboard/src/components/contract-components/contract-publish-form/index.tsx b/apps/dashboard/src/components/contract-components/contract-publish-form/index.tsx
index 9dc0c63ef4f..3073722c194 100644
--- a/apps/dashboard/src/components/contract-components/contract-publish-form/index.tsx
+++ b/apps/dashboard/src/components/contract-components/contract-publish-form/index.tsx
@@ -1,5 +1,4 @@
"use client";
-import { getThirdwebClient } from "@/constants/thirdweb.server";
import { useDashboardRouter } from "@/lib/DashboardRouter";
import { useIsomorphicLayoutEffect } from "@/lib/useIsomorphicLayoutEffect";
import { CustomConnectWallet } from "@3rdweb-sdk/react/components/connect-wallet";
@@ -21,6 +20,7 @@ import {
} from "thirdweb/extensions/thirdweb";
import { useActiveAccount, useSendAndConfirmTransaction } from "thirdweb/react";
import { Button, Text } from "tw-components";
+import { useThirdwebClient } from "../../../@/constants/thirdweb.client";
import { useEns, useFunctionParamsFromABI } from "../hooks";
import { ContractParamsFieldset } from "./contract-params-fieldset";
import { FactoryFieldset } from "./factory-fieldset";
@@ -33,7 +33,7 @@ export function ContractPublishForm(props: {
onPublishSuccess: () => Promise;
jwt: string;
}) {
- const client = getThirdwebClient(props.jwt);
+ const client = useThirdwebClient(props.jwt);
const [customFactoryAbi, setCustomFactoryAbi] = useState([]);
const [fieldsetToShow, setFieldsetToShow] = useState<
"landing" | "factory" | "contractParams" | "implParams" | "networks"
diff --git a/apps/dashboard/src/components/contract-components/contract-publish-form/landing-fieldset.tsx b/apps/dashboard/src/components/contract-components/contract-publish-form/landing-fieldset.tsx
index 0dcb4facf94..7a7408608cc 100644
--- a/apps/dashboard/src/components/contract-components/contract-publish-form/landing-fieldset.tsx
+++ b/apps/dashboard/src/components/contract-components/contract-publish-form/landing-fieldset.tsx
@@ -28,6 +28,7 @@ import {
Link,
Text,
} from "tw-components";
+import { useThirdwebClient } from "../../../@/constants/thirdweb.client";
import { MarkdownRenderer } from "../published-contract/markdown-renderer";
import { ExternalLinksFieldset } from "./external-links-fieldset";
@@ -40,6 +41,7 @@ export const LandingFieldset: React.FC = ({
latestVersion,
placeholderVersion,
}) => {
+ const client = useThirdwebClient();
const form = useFormContext();
const logoUrl = useImageFileOrUrl(form.watch("logo"));
@@ -103,7 +105,7 @@ export const LandingFieldset: React.FC = ({
alt=""
w="100%"
h="100%"
- src={replaceIpfsUrl(fileUrl)}
+ src={replaceIpfsUrl(fileUrl, client)}
borderRadius="full"
/>
)}
diff --git a/apps/dashboard/src/components/contract-components/contract-table/index.tsx b/apps/dashboard/src/components/contract-components/contract-table/index.tsx
index 5190091d671..82e7cc085c9 100644
--- a/apps/dashboard/src/components/contract-components/contract-table/index.tsx
+++ b/apps/dashboard/src/components/contract-components/contract-table/index.tsx
@@ -8,21 +8,23 @@ import {
TableRow,
} from "@/components/ui/table";
import Link from "next/link";
+import type { ThirdwebClient } from "thirdweb";
import { fetchDeployMetadata } from "../fetchDeployMetadata";
import { ContractIdImage } from "../shared/contract-id-image";
type DeployableContractTableProps = {
contractIds: string[];
context: "deploy" | "publish";
+ client: ThirdwebClient;
};
export async function DeployableContractTable(
props: DeployableContractTableProps,
) {
- const { contractIds, context } = props;
+ const { contractIds, context, client } = props;
const deployedContractMetadata = await Promise.all(
contractIds.map(async (id) => {
- const res = await fetchDeployMetadata(id);
+ const res = await fetchDeployMetadata(id, client);
return {
contractId: id,
...res,
@@ -61,7 +63,10 @@ export async function DeployableContractTable(
>
{/* Icon */}
-
+
{/* name */}
diff --git a/apps/dashboard/src/components/contract-components/fetch-contracts-with-versions.ts b/apps/dashboard/src/components/contract-components/fetch-contracts-with-versions.ts
index b0797f01da5..362320d4f8d 100644
--- a/apps/dashboard/src/components/contract-components/fetch-contracts-with-versions.ts
+++ b/apps/dashboard/src/components/contract-components/fetch-contracts-with-versions.ts
@@ -1,4 +1,3 @@
-import { getThirdwebClient } from "@/constants/thirdweb.server";
import { type ThirdwebClient, isAddress } from "thirdweb";
import { fetchDeployMetadata } from "thirdweb/contract";
import { resolveAddress } from "thirdweb/extensions/ens";
@@ -18,8 +17,8 @@ export function mapThirdwebPublisher(publisher: string) {
export async function fetchPublishedContractVersions(
publisherAddress: string,
contractId: string,
+ client: ThirdwebClient,
) {
- const client = getThirdwebClient();
const sortedVersions = await getSortedPublishedContractVersions({
publisherAddress,
contractId,
@@ -80,9 +79,8 @@ async function getSortedPublishedContractVersions(params: {
export async function fetchLatestPublishedContractVersion(
publisherAddress: string,
contractId: string,
+ client: ThirdwebClient,
) {
- const client = getThirdwebClient();
-
const sortedVersions = await getSortedPublishedContractVersions({
publisherAddress,
contractId,
@@ -104,12 +102,14 @@ export async function fetchLatestPublishedContractVersion(
export async function fetchPublishedContractVersion(
publisherAddress: string,
contractId: string,
+ client: ThirdwebClient,
version = "latest",
) {
if (version === "latest") {
const latestVersion = await fetchLatestPublishedContractVersion(
publisherAddress,
contractId,
+ client,
);
return latestVersion || null;
@@ -118,6 +118,7 @@ export async function fetchPublishedContractVersion(
const allVersions = await fetchPublishedContractVersions(
publisherAddress,
contractId,
+ client,
);
if (allVersions.length === 0) {
diff --git a/apps/dashboard/src/components/contract-components/fetchDeployMetadata.ts b/apps/dashboard/src/components/contract-components/fetchDeployMetadata.ts
index c2a0971495c..a31f3136b69 100644
--- a/apps/dashboard/src/components/contract-components/fetchDeployMetadata.ts
+++ b/apps/dashboard/src/components/contract-components/fetchDeployMetadata.ts
@@ -1,16 +1,19 @@
-import { getThirdwebClient } from "@/constants/thirdweb.server";
+import type { ThirdwebClient } from "thirdweb";
import { fetchDeployMetadata as sdkFetchDeployMetadata } from "thirdweb/contract";
import { removeUndefinedFromObjectDeep } from "../../utils/object";
import type { ContractId } from "./types";
// metadata PRE publish, only has the compiler output info (from CLI)
-export async function fetchDeployMetadata(contractId: string) {
+export async function fetchDeployMetadata(
+ contractId: string,
+ client: ThirdwebClient,
+) {
const contractIdIpfsHash = toContractIdIpfsHash(contractId);
return removeUndefinedFromObjectDeep(
await sdkFetchDeployMetadata({
- client: getThirdwebClient(),
+ client,
uri: contractIdIpfsHash,
}),
);
diff --git a/apps/dashboard/src/components/contract-components/fetchPublishedContracts.ts b/apps/dashboard/src/components/contract-components/fetchPublishedContracts.ts
index a8c199c3db7..60b0f8e5155 100644
--- a/apps/dashboard/src/components/contract-components/fetchPublishedContracts.ts
+++ b/apps/dashboard/src/components/contract-components/fetchPublishedContracts.ts
@@ -1,5 +1,5 @@
-import { getThirdwebClient } from "@/constants/thirdweb.server";
import { resolveEns } from "lib/ens";
+import type { ThirdwebClient } from "thirdweb";
import {
getAllPublishedContracts,
getContractPublisher,
@@ -7,12 +7,16 @@ import {
import { fetchDeployMetadata } from "./fetchDeployMetadata";
// TODO: clean this up, jesus
-export async function fetchPublishedContracts(address?: string | null) {
+export async function fetchPublishedContracts(params: {
+ address?: string | null;
+ client: ThirdwebClient;
+}) {
+ const { address, client } = params;
try {
if (!address) {
return [];
}
- const resolvedAddress = (await resolveEns(address)).address;
+ const resolvedAddress = (await resolveEns(address, client)).address;
if (!resolvedAddress) {
return [];
@@ -20,7 +24,7 @@ export async function fetchPublishedContracts(address?: string | null) {
const tempResult = (
(await getAllPublishedContracts({
- contract: getContractPublisher(getThirdwebClient()),
+ contract: getContractPublisher(client),
publisher: resolvedAddress,
})) || []
)
@@ -30,7 +34,7 @@ export async function fetchPublishedContracts(address?: string | null) {
return await Promise.all(
tempResult.map(async (c) => ({
...c,
- metadata: await fetchDeployMetadata(c.publishMetadataUri),
+ metadata: await fetchDeployMetadata(c.publishMetadataUri, client),
})),
);
} catch (e) {
diff --git a/apps/dashboard/src/components/contract-components/fetchPublishedContractsFromDeploy.ts b/apps/dashboard/src/components/contract-components/fetchPublishedContractsFromDeploy.ts
index 0c54c29b90e..2cd3e9056cf 100644
--- a/apps/dashboard/src/components/contract-components/fetchPublishedContractsFromDeploy.ts
+++ b/apps/dashboard/src/components/contract-components/fetchPublishedContractsFromDeploy.ts
@@ -22,5 +22,7 @@ export async function fetchPublishedContractsFromDeploy(options: {
compilerMetadataUri: contractUri,
});
- return await Promise.all(publishURIs.map((uri) => fetchDeployMetadata(uri)));
+ return await Promise.all(
+ publishURIs.map((uri) => fetchDeployMetadata(uri, client)),
+ );
}
diff --git a/apps/dashboard/src/components/contract-components/hooks.ts b/apps/dashboard/src/components/contract-components/hooks.ts
index e514eea8517..33f808bee20 100644
--- a/apps/dashboard/src/components/contract-components/hooks.ts
+++ b/apps/dashboard/src/components/contract-components/hooks.ts
@@ -6,7 +6,7 @@ import type { Abi } from "abitype";
import { resolveEns } from "lib/ens";
import { useV5DashboardChain } from "lib/v5-adapter";
import { useMemo } from "react";
-import type { ThirdwebContract } from "thirdweb";
+import type { ThirdwebClient, ThirdwebContract } from "thirdweb";
import { getContract, resolveContractAbi } from "thirdweb/contract";
import { isAddress, isValidENSName } from "thirdweb/utils";
import {
@@ -20,6 +20,7 @@ export function useAllVersions(
publisherAddress: string | undefined,
contractId: string | undefined,
) {
+ const client = useThirdwebClient();
return useQuery({
queryKey: ["all-releases", publisherAddress, contractId],
queryFn: () => {
@@ -27,7 +28,11 @@ export function useAllVersions(
// should never happen because we check for this in the enabled check
throw new Error("publisherAddress or contractId is not defined");
}
- return fetchPublishedContractVersions(publisherAddress, contractId);
+ return fetchPublishedContractVersions(
+ publisherAddress,
+ contractId,
+ client,
+ );
},
enabled: !!publisherAddress && !!contractId,
@@ -104,17 +109,22 @@ export type PublishedContractDetails = Awaited<
>[number];
export function usePublishedContractsQuery(address?: string) {
+ const client = useThirdwebClient();
return useQuery({
queryKey: ["published-contracts", address],
- queryFn: () => fetchPublishedContracts(address),
+ queryFn: () => fetchPublishedContracts({ address, client }),
enabled: !!address,
});
}
-function ensQuery(addressOrEnsName?: string) {
+function ensQuery(params: {
+ addressOrEnsName?: string;
+ client: ThirdwebClient;
+}) {
+ let addressOrEnsName = params.addressOrEnsName;
+
// if the address is `thirdweb.eth` we actually want `deployer.thirdweb.eth` here...
if (addressOrEnsName === "thirdweb.eth") {
- // biome-ignore lint/style/noParameterAssign: FIXME
addressOrEnsName = "deployer.thirdweb.eth";
}
const placeholderData = {
@@ -134,14 +144,15 @@ function ensQuery(addressOrEnsName?: string) {
throw new Error("Invalid address or ENS name.");
}
- const { address, ensName } = await resolveEns(addressOrEnsName).catch(
- () => ({
- address: isAddress(addressOrEnsName || "")
- ? addressOrEnsName || null
- : null,
- ensName: null,
- }),
- );
+ const { address, ensName } = await resolveEns(
+ addressOrEnsName,
+ params.client,
+ ).catch(() => ({
+ address: isAddress(addressOrEnsName || "")
+ ? addressOrEnsName || null
+ : null,
+ ensName: null,
+ }));
if (isValidENSName(addressOrEnsName) && !address) {
throw new Error("Failed to resolve ENS name.");
@@ -166,7 +177,8 @@ function ensQuery(addressOrEnsName?: string) {
}
export function useEns(addressOrEnsName?: string) {
- return useQuery(ensQuery(addressOrEnsName));
+ const client = useThirdwebClient();
+ return useQuery(ensQuery({ addressOrEnsName, client }));
}
export function useContractEvents(abi: Abi) {
diff --git a/apps/dashboard/src/components/contract-components/published-contract/index.tsx b/apps/dashboard/src/components/contract-components/published-contract/index.tsx
index ea87c95b616..a4d328bc261 100644
--- a/apps/dashboard/src/components/contract-components/published-contract/index.tsx
+++ b/apps/dashboard/src/components/contract-components/published-contract/index.tsx
@@ -191,7 +191,10 @@ export const PublishedContract: React.FC = ({
diff --git a/apps/dashboard/src/components/contract-components/shared/contract-id-image.tsx b/apps/dashboard/src/components/contract-components/shared/contract-id-image.tsx
index 1ce8303ee6f..840bb3798dc 100644
--- a/apps/dashboard/src/components/contract-components/shared/contract-id-image.tsx
+++ b/apps/dashboard/src/components/contract-components/shared/contract-id-image.tsx
@@ -2,15 +2,18 @@
import { replaceIpfsUrl } from "lib/sdk";
import type { StaticImageData } from "next/image";
import Image from "next/image";
+import type { ThirdwebClient } from "thirdweb";
import type { FetchDeployMetadataResult } from "thirdweb/contract";
import generalContractIcon from "../../../../public/assets/tw-icons/general.png";
type ContractIdImageProps = {
deployedMetadataResult: FetchDeployMetadataResult;
+ client: ThirdwebClient;
};
export const ContractIdImage: React.FC = ({
deployedMetadataResult,
+ client,
}) => {
const logo = deployedMetadataResult.logo;
@@ -21,7 +24,11 @@ export const ContractIdImage: React.FC = ({
if (logo) {
return (
-
+
);
}
diff --git a/apps/dashboard/src/components/contract-functions/interactive-abi-function.tsx b/apps/dashboard/src/components/contract-functions/interactive-abi-function.tsx
index ff5fe4be965..a8ade90f858 100644
--- a/apps/dashboard/src/components/contract-functions/interactive-abi-function.tsx
+++ b/apps/dashboard/src/components/contract-functions/interactive-abi-function.tsx
@@ -481,7 +481,10 @@ export const InteractiveAbiFunction: React.FC = (
formattedResponseData.data.startsWith("ipfs://") && (
null);
diff --git a/apps/dashboard/src/components/explore/contract-row/index.tsx b/apps/dashboard/src/components/explore/contract-row/index.tsx
index 876248c01ff..0c62ac43add 100644
--- a/apps/dashboard/src/components/explore/contract-row/index.tsx
+++ b/apps/dashboard/src/components/explore/contract-row/index.tsx
@@ -2,13 +2,15 @@ import type { ExploreCategory } from "data/explore";
import { ArrowRightIcon } from "lucide-react";
import Link from "next/link";
import { Suspense } from "react";
+import type { ThirdwebClient } from "thirdweb";
import { ContractCard, ContractCardSkeleton } from "../contract-card";
interface ContractRowProps {
category: ExploreCategory;
+ client: ThirdwebClient;
}
-export function ContractRow({ category }: ContractRowProps) {
+export function ContractRow({ category, client }: ContractRowProps) {
return (
{/* Title, Description + View all link */}
@@ -75,6 +77,7 @@ export function ContractRow({ category }: ContractRowProps) {
fallback={}
>
{
- const src = ipfsSrc ? replaceIpfsUrl(ipfsSrc) : fallbackChainIcon;
+ const client = useThirdwebClient();
+ const src = ipfsSrc ? replaceIpfsUrl(ipfsSrc, client) : fallbackChainIcon;
return (
= z
.custom((ens) => typeof ens === "string" && isValidENSName(ens))
- .transform(async (ens) => (await resolveEns(ens)).address)
+ // TODO - move this schema inside component to use client with authToken, teamId filled in
+ .transform(
+ async (ens) =>
+ (await resolveEns(ens, getThirdwebClient(undefined))).address,
+ )
.refine(
(address): address is `0x${string}` => !!address && isAddress(address),
{
diff --git a/apps/dashboard/src/core-ui/batch-upload/batch-table.tsx b/apps/dashboard/src/core-ui/batch-upload/batch-table.tsx
index a9c75bca356..7116b09cf6c 100644
--- a/apps/dashboard/src/core-ui/batch-upload/batch-table.tsx
+++ b/apps/dashboard/src/core-ui/batch-upload/batch-table.tsx
@@ -28,11 +28,13 @@ import {
import { useMemo } from "react";
import { type Column, usePagination, useTable } from "react-table";
import type { NFTInput } from "thirdweb/utils";
+import { useThirdwebClient } from "../../@/constants/thirdweb.client";
const FileImage: React.FC = ({ src, ...props }) => {
+ const client = useThirdwebClient();
const img = useImageFileOrUrl(
typeof src === "string" && src.startsWith("ipfs://")
- ? replaceIpfsUrl(src)
+ ? replaceIpfsUrl(src, client)
: src,
);
return ;
@@ -41,9 +43,10 @@ const FileImage: React.FC = ({ src, ...props }) => {
const FileVideo: React.FC<
BoxProps & Omit, "ref">
> = ({ src, ...props }) => {
+ const client = useThirdwebClient();
const video = useImageFileOrUrl(
typeof src === "string" && src.startsWith("ipfs://")
- ? replaceIpfsUrl(src)
+ ? replaceIpfsUrl(src, client)
: src,
);
return ;
diff --git a/apps/dashboard/src/lib/ens.ts b/apps/dashboard/src/lib/ens.ts
index a55c67964f7..a01d8b4b74b 100644
--- a/apps/dashboard/src/lib/ens.ts
+++ b/apps/dashboard/src/lib/ens.ts
@@ -1,5 +1,4 @@
-import { getThirdwebClient } from "@/constants/thirdweb.server";
-import { isAddress } from "thirdweb";
+import { type ThirdwebClient, isAddress } from "thirdweb";
import { resolveAddress, resolveName } from "thirdweb/extensions/ens";
import { isValidENSName } from "thirdweb/utils";
@@ -10,12 +9,13 @@ interface ENSResolveResult {
export async function resolveEns(
ensNameOrAddress: string,
+ client: ThirdwebClient,
): Promise {
if (isAddress(ensNameOrAddress)) {
return {
address: ensNameOrAddress,
ensName: await resolveName({
- client: getThirdwebClient(),
+ client,
address: ensNameOrAddress,
}),
};
@@ -26,7 +26,7 @@ export async function resolveEns(
}
const address = await resolveAddress({
- client: getThirdwebClient(),
+ client,
name: ensNameOrAddress,
});
diff --git a/apps/dashboard/src/lib/rpc.ts b/apps/dashboard/src/lib/rpc.ts
index 1165556a44f..9a7fb4900fc 100644
--- a/apps/dashboard/src/lib/rpc.ts
+++ b/apps/dashboard/src/lib/rpc.ts
@@ -1,18 +1,19 @@
import { isProd } from "@/constants/env";
-import { getThirdwebClient } from "@/constants/thirdweb.server";
import { defineDashboardChain } from "lib/defineDashboardChain";
+import type { ThirdwebClient } from "thirdweb";
import { type ChainMetadata, getRpcUrlForChain } from "thirdweb/chains";
import { hostnameEndsWith } from "../utils/url";
export function getDashboardChainRpc(
chainId: number,
dashboardChain: ChainMetadata | undefined,
+ client: ThirdwebClient,
) {
try {
const rpcUrl = getRpcUrlForChain({
// eslint-disable-next-line no-restricted-syntax
chain: defineDashboardChain(chainId, dashboardChain),
- client: getThirdwebClient(),
+ client,
});
// based on the environment hit dev or production
if (hostnameEndsWith(rpcUrl, "rpc.thirdweb.com")) {
diff --git a/apps/dashboard/src/lib/sdk.ts b/apps/dashboard/src/lib/sdk.ts
index 54c8f982d81..13b0fd6403d 100644
--- a/apps/dashboard/src/lib/sdk.ts
+++ b/apps/dashboard/src/lib/sdk.ts
@@ -1,12 +1,12 @@
-import { getThirdwebClient } from "@/constants/thirdweb.server";
+import type { ThirdwebClient } from "thirdweb";
import { resolveScheme } from "thirdweb/storage";
-export function replaceIpfsUrl(uri: string) {
+export function replaceIpfsUrl(uri: string, client: ThirdwebClient) {
try {
// eslint-disable-next-line no-restricted-syntax
return resolveScheme({
uri,
- client: getThirdwebClient(),
+ client,
});
} catch (err) {
console.error("error resolving ipfs url", uri, err);
diff --git a/apps/dashboard/src/lib/wallet/nfts/alchemy.ts b/apps/dashboard/src/lib/wallet/nfts/alchemy.ts
index 13bb4608ee2..36b5e0b9f79 100644
--- a/apps/dashboard/src/lib/wallet/nfts/alchemy.ts
+++ b/apps/dashboard/src/lib/wallet/nfts/alchemy.ts
@@ -1,21 +1,16 @@
-import { getThirdwebClient } from "@/constants/thirdweb.server";
+import "server-only";
+
import { download } from "thirdweb/storage";
import type { NFTMetadata } from "thirdweb/utils";
+import { getUserThirdwebClient } from "../../../app/api/lib/getAuthToken";
import { handleArbitraryTokenURI, shouldDownloadURI } from "./tokenUri";
import {
type AlchemySupportedChainId,
type GenerateURLParams,
type WalletNFT,
- alchemySupportedChainIds,
alchemySupportedChainIdsMap,
} from "./types";
-export function isAlchemySupported(
- chainId: number,
-): chainId is AlchemySupportedChainId {
- return alchemySupportedChainIds.includes(chainId.toString());
-}
-
export function generateAlchemyUrl({ chainId, owner }: GenerateURLParams) {
const url = new URL(
`https://${
@@ -30,6 +25,8 @@ export async function transformAlchemyResponseToNFT(
alchemyResponse: AlchemyResponse,
owner: string,
): Promise {
+ const client = await getUserThirdwebClient();
+
return (
await Promise.all(
alchemyResponse.ownedNfts.map(async (alchemyNFT) => {
@@ -42,7 +39,7 @@ export async function transformAlchemyResponseToNFT(
metadata: shouldDownloadURI(rawUri)
? await download({
uri: handleArbitraryTokenURI(rawUri),
- client: getThirdwebClient(),
+ client,
})
.then((res) => res.json())
.catch(() => ({}))
diff --git a/apps/dashboard/src/lib/wallet/nfts/isAlchemySupported.ts b/apps/dashboard/src/lib/wallet/nfts/isAlchemySupported.ts
new file mode 100644
index 00000000000..8f3629a6377
--- /dev/null
+++ b/apps/dashboard/src/lib/wallet/nfts/isAlchemySupported.ts
@@ -0,0 +1,10 @@
+import {
+ type AlchemySupportedChainId,
+ alchemySupportedChainIds,
+} from "./types";
+
+export function isAlchemySupported(
+ chainId: number,
+): chainId is AlchemySupportedChainId {
+ return alchemySupportedChainIds.includes(chainId.toString());
+}
diff --git a/apps/dashboard/src/lib/wallet/nfts/isMoralisSupported.ts b/apps/dashboard/src/lib/wallet/nfts/isMoralisSupported.ts
new file mode 100644
index 00000000000..d319202e245
--- /dev/null
+++ b/apps/dashboard/src/lib/wallet/nfts/isMoralisSupported.ts
@@ -0,0 +1,10 @@
+import {
+ type MoralisSupportedChainId,
+ moralisSupportedChainIds,
+} from "./types";
+
+export function isMoralisSupported(
+ chainId: number,
+): chainId is MoralisSupportedChainId {
+ return moralisSupportedChainIds.includes(chainId.toString());
+}
diff --git a/apps/dashboard/src/lib/wallet/nfts/moralis.ts b/apps/dashboard/src/lib/wallet/nfts/moralis.ts
index 5d2824fd913..b6530e6f523 100644
--- a/apps/dashboard/src/lib/wallet/nfts/moralis.ts
+++ b/apps/dashboard/src/lib/wallet/nfts/moralis.ts
@@ -1,18 +1,9 @@
-import { getThirdwebClient } from "@/constants/thirdweb.server";
+import "server-only";
+
import { download } from "thirdweb/storage";
+import { getUserThirdwebClient } from "../../../app/api/lib/getAuthToken";
import { handleArbitraryTokenURI, shouldDownloadURI } from "./tokenUri";
-import {
- type GenerateURLParams,
- type MoralisSupportedChainId,
- type WalletNFT,
- moralisSupportedChainIds,
-} from "./types";
-
-export function isMoralisSupported(
- chainId: number,
-): chainId is MoralisSupportedChainId {
- return moralisSupportedChainIds.includes(chainId.toString());
-}
+import type { GenerateURLParams, WalletNFT } from "./types";
export function generateMoralisUrl({ chainId, owner }: GenerateURLParams) {
const url = new URL(`https://deep-index.moralis.io/api/v2/${owner}/nft`);
@@ -28,6 +19,8 @@ export async function transformMoralisResponseToNFT(
owner: string,
chainId: number,
): Promise {
+ const client = await getUserThirdwebClient();
+
return (
await Promise.all(
moralisResponse.result.map(async (moralisNft) => {
@@ -39,7 +32,7 @@ export async function transformMoralisResponseToNFT(
metadata: shouldDownloadURI(moralisNft.token_uri)
? await download({
uri: handleArbitraryTokenURI(moralisNft.token_uri),
- client: getThirdwebClient(),
+ client,
})
.then((res) => res.json())
.catch(() => ({}))
diff --git a/apps/dashboard/src/stories/utils.tsx b/apps/dashboard/src/stories/utils.tsx
index 3673008d9a5..047fe616122 100644
--- a/apps/dashboard/src/stories/utils.tsx
+++ b/apps/dashboard/src/stories/utils.tsx
@@ -1,5 +1,6 @@
import { Badge } from "@/components/ui/badge";
import { INITIAL_VIEWPORTS } from "@storybook/addon-viewport";
+import { getThirdwebClient } from "../@/constants/thirdweb.server";
function StoryBadge(props: {
label: string;
@@ -42,3 +43,8 @@ export function storybookLog(...mesages: unknown[]) {
...mesages,
);
}
+
+export const storybookThirdwebClient = getThirdwebClient({
+ jwt: null,
+ teamId: undefined,
+});