Skip to content

Commit 70d65e2

Browse files
committed
Merge remote-tracking branch 'origin/main' into mintable-module
2 parents c0455f0 + f40d247 commit 70d65e2

File tree

141 files changed

+3392
-561
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

141 files changed

+3392
-561
lines changed

.changeset/early-shoes-applaud.md

Lines changed: 0 additions & 5 deletions
This file was deleted.

.changeset/fuzzy-olives-prove.md

Lines changed: 0 additions & 5 deletions
This file was deleted.

.changeset/new-rules-buy.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"thirdweb": patch
3+
---
4+
5+
Allow smart accounts to switch chains between zk and non zk chains

.changeset/smart-chicken-beam.md

Lines changed: 0 additions & 5 deletions
This file was deleted.

.changeset/three-dancers-hear.md

Lines changed: 0 additions & 5 deletions
This file was deleted.

apps/dashboard/src/@/components/blocks/Img.tsx

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
/* eslint-disable @next/next/no-img-element */
22
"use client";
3-
import { useState } from "react";
3+
import { useRef, useState } from "react";
4+
import { useIsomorphicLayoutEffect } from "../../lib/useIsomorphicLayoutEffect";
45
import { cn } from "../../lib/utils";
56

67
type imgElementProps = React.DetailedHTMLProps<
@@ -25,19 +26,39 @@ export function Img(props: imgElementProps) {
2526
const { className, fallback, skeleton, ...restProps } = props;
2627
const defaultSkeleton = <div className="animate-pulse bg-accent" />;
2728
const defaultFallback = <div className="bg-muted" />;
29+
const imgRef = useRef<HTMLImageElement>(null);
30+
31+
useIsomorphicLayoutEffect(() => {
32+
const imgEl = imgRef.current;
33+
if (!imgEl) {
34+
return;
35+
}
36+
if (imgEl.complete) {
37+
setStatus("loaded");
38+
} else {
39+
function handleLoad() {
40+
setStatus("loaded");
41+
}
42+
imgEl.addEventListener("load", handleLoad);
43+
return () => {
44+
imgEl.removeEventListener("load", handleLoad);
45+
};
46+
}
47+
}, []);
2848

2949
return (
3050
<div className="relative">
3151
<img
3252
{...restProps}
33-
onLoad={() => {
34-
setStatus("loaded");
35-
}}
53+
// avoid setting empty src string to prevent request to the entire page
54+
src={restProps.src || undefined}
55+
ref={imgRef}
3656
onError={() => {
3757
setStatus("fallback");
3858
}}
3959
style={{
4060
opacity: status === "loaded" ? 1 : 0,
61+
...restProps.style,
4162
}}
4263
alt={restProps.alt || ""}
4364
className={cn(
@@ -48,6 +69,7 @@ export function Img(props: imgElementProps) {
4869

4970
{status !== "loaded" && (
5071
<div
72+
style={restProps.style}
5173
className={cn(
5274
"fade-in-0 absolute inset-0 overflow-hidden transition-opacity duration-300 [&>*]:h-full [&>*]:w-full",
5375
className,
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
"use client";
2+
3+
import { Spinner } from "@/components/ui/Spinner/Spinner";
4+
5+
export function GenericLoadingPage() {
6+
return (
7+
<div className="flex min-h-[500px] grow items-center justify-center rounded-lg border border-border">
8+
<Spinner className="size-10" />
9+
</div>
10+
);
11+
}

apps/dashboard/src/@3rdweb-sdk/react/hooks/useApi.ts

Lines changed: 61 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -12,21 +12,24 @@ import { useLoggedInUser } from "./useLoggedInUser";
1212

1313
// FIXME: We keep repeating types, API server should provide them
1414

15-
export enum AccountStatus {
16-
NoCustomer = "noCustomer",
17-
NoPayment = "noPayment",
18-
PaymentVerification = "paymentVerification",
19-
ValidPayment = "validPayment",
20-
InvalidPayment = "invalidPayment",
21-
InvalidPaymentMethod = "invalidPaymentMethod",
22-
}
23-
24-
export enum AccountPlan {
25-
Free = "free",
26-
Growth = "growth",
27-
Pro = "pro",
28-
Enterprise = "enterprise",
29-
}
15+
export const accountStatus = {
16+
noCustomer: "noCustomer",
17+
noPayment: "noPayment",
18+
paymentVerification: "paymentVerification",
19+
validPayment: "validPayment",
20+
invalidPayment: "invalidPayment",
21+
invalidPaymentMethod: "invalidPaymentMethod",
22+
} as const;
23+
24+
export const accountPlan = {
25+
free: "free",
26+
growth: "growth",
27+
pro: "pro",
28+
enterprise: "enterprise",
29+
} as const;
30+
31+
export type AccountStatus = (typeof accountStatus)[keyof typeof accountStatus];
32+
export type AccountPlan = (typeof accountPlan)[keyof typeof accountPlan];
3033

3134
export type AuthorizedWallet = {
3235
id: string;
@@ -235,6 +238,12 @@ export interface WalletStats {
235238
walletType: string;
236239
}
237240

241+
export interface InAppWalletStats {
242+
date: string;
243+
authenticationMethod: string;
244+
uniqueWalletsConnected: number;
245+
}
246+
238247
export interface UserOpStats {
239248
date: string;
240249
successful: number;
@@ -436,6 +445,43 @@ async function getUserOpUsage(args: {
436445
return json.data;
437446
}
438447

448+
export async function getInAppWalletUsage(args: {
449+
clientId: string;
450+
from?: Date;
451+
to?: Date;
452+
period?: "day" | "week" | "month" | "year" | "all";
453+
}) {
454+
const { clientId, from, to, period } = args;
455+
456+
const searchParams = new URLSearchParams();
457+
searchParams.append("clientId", clientId);
458+
if (from) {
459+
searchParams.append("from", from.toISOString());
460+
}
461+
if (to) {
462+
searchParams.append("to", to.toISOString());
463+
}
464+
if (period) {
465+
searchParams.append("period", period);
466+
}
467+
const res = await fetch(
468+
`${THIRDWEB_ANALYTICS_API_HOST}/v1/wallets/in-app?${searchParams.toString()}`,
469+
{
470+
method: "GET",
471+
headers: {
472+
"Content-Type": "application/json",
473+
},
474+
},
475+
);
476+
const json = await res?.json();
477+
478+
if (!res || res.status !== 200) {
479+
throw new Error(json.message);
480+
}
481+
482+
return json.data;
483+
}
484+
439485
export function useUserOpUsageAggregate(args: {
440486
clientId: string;
441487
from?: Date;
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
"use client";
2+
3+
export { GenericLoadingPage as default } from "@/components/blocks/skeletons/GenericLoadingPage";

apps/dashboard/src/app/(dashboard)/dashboard/connect/account-abstraction/[clientId]/page.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { AccountStatus } from "@3rdweb-sdk/react/hooks/useApi";
1+
import { accountStatus } from "@3rdweb-sdk/react/hooks/useApi";
22
import { SmartWalletsBillingAlert } from "components/settings/ApiKeys/Alerts";
33
import { ConnectSDKCard } from "components/shared/ConnectSDKCard";
44
import { SmartWallets } from "components/smart-wallets";
@@ -38,7 +38,7 @@ export default async function Page(props: {
3838
const hasSmartWalletsWithoutBilling = apiKeys.find((k) =>
3939
k.services?.find(
4040
(s) =>
41-
dashboardAccount.status !== AccountStatus.ValidPayment &&
41+
dashboardAccount.status !== accountStatus.validPayment &&
4242
s.name === "bundler",
4343
),
4444
);

0 commit comments

Comments
 (0)