Skip to content

Commit f054236

Browse files
committed
Merge remote-tracking branch 'origin/main' into ph/07-04-feat_webhook_analytics_tab
2 parents 42f6d84 + adfa56b commit f054236

File tree

487 files changed

+19359
-19913
lines changed

Some content is hidden

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

487 files changed

+19359
-19913
lines changed

.github/workflows/CI.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ jobs:
6363
- name: Setup Biome
6464
uses: biomejs/setup-biome@a9763ed3d2388f5746f9dc3e1a55df7f4609bc89 # v2.5.1
6565
with:
66-
version: 2.0.4
66+
version: 2.0.6
6767

6868
- run: pnpm lint
6969

apps/dashboard/biome.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
{
2-
"$schema": "https://biomejs.dev/schemas/2.0.4/schema.json",
2+
"$schema": "https://biomejs.dev/schemas/2.0.6/schema.json",
33
"extends": "//"
44
}

apps/dashboard/framer-rewrites.js

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,15 @@ module.exports = [
1414
"/in-app-wallets",
1515
"/transactions",
1616
// -- end build category
17-
// -- storage
17+
18+
// -- scale category
19+
"/rpc",
20+
"/insight",
1821
"/storage",
22+
// -- end scale category
23+
1924
// -- nebula
2025
"/nebula",
21-
// --insight
22-
"/insight",
2326
// -- contracts
2427
"/contracts",
2528
"/contracts/modular-contracts",

apps/dashboard/next.config.ts

Lines changed: 19 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -208,35 +208,29 @@ function getConfig(): NextConfig {
208208
const withBundleAnalyzer = require("@next/bundle-analyzer")({
209209
enabled: process.env.ANALYZE === "true",
210210
});
211-
// eslint-disable-next-line @typescript-eslint/no-var-requires
212-
const { withPlausibleProxy } = require("next-plausible");
211+
213212
// eslint-disable-next-line @typescript-eslint/no-var-requires
214213
const { withSentryConfig } = require("@sentry/nextjs");
215214
return withBundleAnalyzer(
216-
withPlausibleProxy({
217-
customDomain: "https://pl.thirdweb.com",
218-
scriptName: "pl",
219-
})(
220-
withSentryConfig(
221-
{
222-
...baseNextConfig,
223-
// @ts-expect-error - this is a valid option
224-
webpack: (config) => {
225-
if (config.cache) {
226-
config.cache = Object.freeze({
227-
type: "memory",
228-
});
229-
}
230-
config.module = {
231-
...config.module,
232-
exprContextCritical: false,
233-
};
234-
// Important: return the modified config
235-
return config;
236-
},
215+
withSentryConfig(
216+
{
217+
...baseNextConfig,
218+
// @ts-expect-error - this is a valid option
219+
webpack: (config) => {
220+
if (config.cache) {
221+
config.cache = Object.freeze({
222+
type: "memory",
223+
});
224+
}
225+
config.module = {
226+
...config.module,
227+
exprContextCritical: false,
228+
};
229+
// Important: return the modified config
230+
return config;
237231
},
238-
SENTRY_OPTIONS,
239-
),
232+
},
233+
SENTRY_OPTIONS,
240234
),
241235
);
242236
}

apps/dashboard/package.json

Lines changed: 25 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
"@chakra-ui/styled-system": "^2.9.2",
55
"@chakra-ui/theme-tools": "^2.1.2",
66
"@emotion/react": "11.14.0",
7-
"@emotion/styled": "11.14.0",
7+
"@emotion/styled": "11.14.1",
88
"@hookform/resolvers": "^3.9.1",
99
"@marsidev/react-turnstile": "^1.1.0",
1010
"@radix-ui/react-accordion": "^1.2.11",
@@ -24,10 +24,10 @@
2424
"@radix-ui/react-slot": "^1.2.3",
2525
"@radix-ui/react-switch": "^1.2.5",
2626
"@radix-ui/react-tooltip": "1.2.7",
27-
"@scalar/api-reference-react": "^0.6.19",
28-
"@sentry/nextjs": "9.29.0",
27+
"@scalar/api-reference-react": "0.7.25",
28+
"@sentry/nextjs": "9.34.0",
2929
"@shazow/whatsabi": "0.22.2",
30-
"@tanstack/react-query": "5.80.7",
30+
"@tanstack/react-query": "5.81.5",
3131
"@tanstack/react-table": "^8.21.3",
3232
"@thirdweb-dev/service-utils": "workspace:*",
3333
"@thirdweb-dev/vault-sdk": "workspace:*",
@@ -41,29 +41,29 @@
4141
"compare-versions": "^6.1.0",
4242
"date-fns": "4.1.0",
4343
"fast-xml-parser": "^5.2.5",
44-
"framer-motion": "12.17.0",
44+
"framer-motion": "12.23.0",
4545
"fuse.js": "7.1.0",
4646
"input-otp": "^1.4.1",
4747
"ioredis": "^5.6.1",
4848
"ipaddr.js": "^2.2.0",
49-
"lucide-react": "0.514.0",
50-
"next": "15.3.3",
51-
"next-plausible": "^3.12.4",
49+
"lucide-react": "0.525.0",
50+
"next": "15.3.5",
5251
"next-themes": "^0.4.6",
5352
"nextjs-toploader": "^1.6.12",
5453
"nuqs": "^2.4.3",
5554
"p-limit": "^6.2.0",
5655
"papaparse": "^5.5.3",
5756
"pluralize": "^8.0.0",
58-
"posthog-js": "1.252.0",
59-
"prettier": "3.5.3",
57+
"posthog-js": "1.256.1",
58+
"posthog-node": "^5.3.1",
59+
"prettier": "3.6.2",
6060
"qrcode": "^1.5.3",
6161
"react": "19.1.0",
6262
"react-children-utilities": "^2.10.0",
6363
"react-day-picker": "^8.10.1",
6464
"react-dom": "19.1.0",
6565
"react-dropzone": "^14.3.8",
66-
"react-error-boundary": "^5.0.0",
66+
"react-error-boundary": "6.0.0",
6767
"react-hook-form": "7.55.0",
6868
"react-markdown": "10.1.0",
6969
"react-table": "^7.8.0",
@@ -72,7 +72,7 @@
7272
"responsive-rsc": "0.0.7",
7373
"server-only": "^0.0.1",
7474
"shiki": "1.27.0",
75-
"sonner": "2.0.5",
75+
"sonner": "2.0.6",
7676
"spdx-correct": "^3.2.0",
7777
"stripe": "17.7.0",
7878
"swagger-ui-react": "^5.24.1",
@@ -82,19 +82,19 @@
8282
"tiny-invariant": "^1.3.3",
8383
"use-debounce": "^10.0.5",
8484
"vaul": "^1.1.2",
85-
"zod": "3.25.67"
85+
"zod": "3.25.75"
8686
},
8787
"devDependencies": {
88-
"@biomejs/biome": "2.0.4",
88+
"@biomejs/biome": "2.0.6",
8989
"@chakra-ui/cli": "^2.4.1",
90-
"@chromatic-com/storybook": "4.0.0",
91-
"@next/bundle-analyzer": "15.3.3",
92-
"@next/eslint-plugin-next": "15.3.3",
93-
"@playwright/test": "1.53.0",
94-
"@storybook/addon-docs": "9.0.8",
95-
"@storybook/addon-links": "9.0.8",
96-
"@storybook/addon-onboarding": "9.0.8",
97-
"@storybook/nextjs": "9.0.8",
90+
"@chromatic-com/storybook": "4.0.1",
91+
"@next/bundle-analyzer": "15.3.5",
92+
"@next/eslint-plugin-next": "15.3.5",
93+
"@playwright/test": "1.53.2",
94+
"@storybook/addon-docs": "9.0.15",
95+
"@storybook/addon-links": "9.0.15",
96+
"@storybook/addon-onboarding": "9.0.15",
97+
"@storybook/nextjs": "9.0.15",
9898
"@types/color": "4.2.0",
9999
"@types/node": "22.14.1",
100100
"@types/papaparse": "^5.3.16",
@@ -112,11 +112,11 @@
112112
"eslint": "8.57.0",
113113
"eslint-config-biome": "1.9.4",
114114
"eslint-plugin-react-compiler": "19.1.0-rc.2",
115-
"eslint-plugin-storybook": "9.0.8",
115+
"eslint-plugin-storybook": "9.0.15",
116116
"knip": "5.60.2",
117117
"next-sitemap": "^4.2.3",
118-
"postcss": "8.5.5",
119-
"storybook": "9.0.8",
118+
"postcss": "8.5.6",
119+
"storybook": "9.0.15",
120120
"tailwindcss": "3.4.17",
121121
"typescript": "5.8.3"
122122
},

apps/dashboard/redirects.js

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -327,13 +327,6 @@ async function redirects() {
327327
permanent: false,
328328
source: "/solutions/chains",
329329
},
330-
// redirect /rpc to portal
331-
{
332-
destination:
333-
"https://portal.thirdweb.com/infrastructure/rpc-edge/overview",
334-
permanent: false,
335-
source: "/rpc-edge",
336-
},
337330
// redirect /sdk to portal
338331
{
339332
destination: "https://portal.thirdweb.com/connect/blockchain-api",
@@ -442,6 +435,11 @@ async function redirects() {
442435
permanent: false,
443436
source: "/engine",
444437
},
438+
{
439+
destination: "/rpc",
440+
permanent: false,
441+
source: "/rpc-edge",
442+
},
445443
...legacyDashboardToTeamRedirects,
446444
...projectPageRedirects,
447445
...teamPageRedirects,

apps/dashboard/src/@/actions/billing.ts

Lines changed: 87 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
"use server";
2+
import "server-only";
23

34
import { getAuthToken } from "@/api/auth-token";
45
import { NEXT_PUBLIC_THIRDWEB_API_HOST } from "@/constants/public-envs";
6+
import type { ChainInfraSKU } from "@/types/billing";
7+
import { getAbsoluteUrl } from "@/utils/vercel";
58

69
export async function reSubscribePlan(options: {
710
teamId: string;
@@ -14,7 +17,10 @@ export async function reSubscribePlan(options: {
1417
}
1518

1619
const res = await fetch(
17-
`${NEXT_PUBLIC_THIRDWEB_API_HOST}/v1/teams/${options.teamId}/checkout/resubscribe-plan`,
20+
new URL(
21+
`/v1/teams/${options.teamId}/checkout/resubscribe-plan`,
22+
NEXT_PUBLIC_THIRDWEB_API_HOST,
23+
),
1824
{
1925
body: JSON.stringify({}),
2026
headers: {
@@ -35,3 +41,83 @@ export async function reSubscribePlan(options: {
3541
status: 200,
3642
};
3743
}
44+
45+
export async function getChainInfraCheckoutURL(options: {
46+
teamSlug: string;
47+
skus: ChainInfraSKU[];
48+
chainId: number;
49+
annual: boolean;
50+
}) {
51+
const token = await getAuthToken();
52+
53+
if (!token) {
54+
return {
55+
error: "You are not logged in",
56+
status: "error",
57+
} as const;
58+
}
59+
60+
const res = await fetch(
61+
new URL(
62+
`/v1/teams/${options.teamSlug}/checkout/create-link`,
63+
NEXT_PUBLIC_THIRDWEB_API_HOST,
64+
),
65+
{
66+
body: JSON.stringify({
67+
annual: options.annual,
68+
baseUrl: getAbsoluteUrl(),
69+
chainId: options.chainId,
70+
skus: options.skus,
71+
}),
72+
headers: {
73+
Authorization: `Bearer ${token}`,
74+
"Content-Type": "application/json",
75+
},
76+
method: "POST",
77+
},
78+
);
79+
if (!res.ok) {
80+
const text = await res.text();
81+
console.error("Failed to create checkout link", text, res.status);
82+
switch (res.status) {
83+
case 402: {
84+
return {
85+
error:
86+
"You have outstanding invoices, please pay these first before re-subscribing.",
87+
status: "error",
88+
} as const;
89+
}
90+
case 429: {
91+
return {
92+
error: "Too many requests, please try again later.",
93+
status: "error",
94+
} as const;
95+
}
96+
case 403: {
97+
return {
98+
error: "You are not authorized to deploy infrastructure.",
99+
status: "error",
100+
} as const;
101+
}
102+
default: {
103+
return {
104+
error: "An unknown error occurred, please try again later.",
105+
status: "error",
106+
} as const;
107+
}
108+
}
109+
}
110+
111+
const json = await res.json();
112+
if (!json.result) {
113+
return {
114+
error: "An unknown error occurred, please try again later.",
115+
status: "error",
116+
} as const;
117+
}
118+
119+
return {
120+
data: json.result as string,
121+
status: "success",
122+
} as const;
123+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import "server-only";
2+
import { PostHog } from "posthog-node";
3+
4+
let posthogServer: PostHog | null = null;
5+
6+
function getPostHogServer(): PostHog | null {
7+
if (!posthogServer && process.env.NEXT_PUBLIC_POSTHOG_KEY) {
8+
posthogServer = new PostHog(process.env.NEXT_PUBLIC_POSTHOG_KEY, {
9+
host: "https://us.i.posthog.com",
10+
});
11+
}
12+
return posthogServer;
13+
}
14+
15+
/**
16+
* Check if a feature flag is enabled for a specific user
17+
* @param flagKey - The feature flag key
18+
* @param userEmail - The user's email address for filtering
19+
*/
20+
export async function isFeatureFlagEnabled(
21+
flagKey: string,
22+
userEmail?: string,
23+
): Promise<boolean> {
24+
try {
25+
const client = getPostHogServer();
26+
if (client && userEmail) {
27+
const isEnabled = await client.isFeatureEnabled(flagKey, userEmail, {
28+
personProperties: {
29+
email: userEmail,
30+
},
31+
});
32+
if (isEnabled !== undefined) {
33+
return isEnabled;
34+
}
35+
}
36+
} catch (error) {
37+
console.error(`Error checking feature flag ${flagKey}:`, error);
38+
}
39+
return false;
40+
}

0 commit comments

Comments
 (0)