Compare commits

..
Author SHA1 Message Date
Joaquim VergesGitHubgithub-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
6d635dc266 Version Packages (#7891)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2025-08-20 10:24:39 -07:00
gregandGitHub 1083316ef6 [SDK] Feature: prepareCreateToken returns prepared transaction (#7872) 2025-08-20 10:06:41 -07:00
Joaquim VergesGitHubgithub-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2c1ec47a04 Version Packages (#7889)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2025-08-20 03:50:57 -07:00
e01af9db71 fix: #7886 (#7887)
Signed-off-by: leo.shi <[email protected]>
Signed-off-by: Jonas Daniels <[email protected]>
Co-authored-by: Jonas Daniels <[email protected]>
2025-08-20 03:41:16 -07:00
Joaquim VergesandGitHub fd7e10d3de [Dashboard] Fix date handling in analytics components (#7885) 2025-08-19 17:59:55 -07:00
Joaquim VergesandGitHub 3126d87740 [Dashboard] improve wallet stats (#7880) 2025-08-19 15:51:01 -07:00
nischitpra b9e63ff0a7 add webhook id to test webhook (#7884)
<!-- start pr-codex -->

## PR-Codex overview
This PR introduces a new optional property `webhook_id` to the `TestWebhookPayload` interface and updates the call to `testWebhook` to include this new property.

### Detailed summary
- Added an optional property `webhook_id` to the `TestWebhookPayload` interface in `webhooks.ts`.
- Updated the `testWebhook` function call in `useTestWebhook.ts` to include `webhook_id` when invoking the function.

> ✨ Ask PR-Codex anything about this PR by commenting with `/codex {your question}`

<!-- end pr-codex -->

<!-- This is an auto-generated comment: release notes by coderabbit.ai -->

## Summary by CodeRabbit

* **Bug Fixes**
  * Test Webhook requests now include the specific webhook ID when available, ensuring the test targets the correct webhook and improving reliability.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2025-08-19 22:35:05 +00:00
Jonas DanielsandGitHub 77053049a5 Always show Chain Infrastructure in sidebar regardless of subscriptions (#7883) 2025-08-19 09:51:09 -07:00
26 changed files with 246 additions and 220 deletions
+7 -40
View File
@@ -13,7 +13,6 @@ import type {
UniversalBridgeWalletStats,
UserOpStats,
WalletStats,
WalletUserStats,
WebhookLatencyStats,
WebhookRequestStats,
WebhookSummaryStats,
@@ -147,7 +146,13 @@ const cached_getWalletConnections = unstable_cache(
}
const json = await res.json();
return json.data as WalletStats[];
return (json.data as WalletStats[]).filter(
(w) =>
w.walletType !== "smart" &&
w.walletType !== "smartWallet" &&
w.walletType !== "inApp" &&
w.walletType !== "inAppWallet",
);
},
["getWalletConnections"],
{
@@ -398,44 +403,6 @@ export function getRpcUsageByType(
return cached_getRpcUsageByType(normalizedParams(params), authToken);
}
const cached_getWalletUsers = unstable_cache(
async (
params: AnalyticsQueryParams,
authToken: string,
): Promise<WalletUserStats[]> => {
const searchParams = buildSearchParams(params);
const res = await fetchAnalytics({
authToken,
url: `v2/sdk/wallet-connects/users?${searchParams.toString()}`,
init: {
method: "GET",
},
});
if (res?.status !== 200) {
const reason = await res?.text();
console.error(
`Failed to fetch wallet user stats: ${res?.status} - ${res.statusText} - ${reason}`,
);
return [];
}
const json = await res.json();
return json.data as WalletUserStats[];
},
["getWalletUsers"],
{
revalidate: 60 * 60, // 1 hour
},
);
export function getWalletUsers(
params: AnalyticsQueryParams,
authToken: string,
) {
return cached_getWalletUsers(normalizedParams(params), authToken);
}
type ActiveStatus = {
bundler: boolean;
storage: boolean;
@@ -58,6 +58,7 @@ interface WebhookSingleResponse {
}
interface TestWebhookPayload {
webhook_id?: string;
webhook_url: string;
type?: "event" | "transaction";
}
@@ -86,7 +86,9 @@ export function getLastNDaysRange(id: DurationId) {
throw new Error(`Invalid duration id: ${id}`);
}
const todayDate = new Date(Date.now());
const todayDate = new Date();
todayDate.setDate(todayDate.getDate() + 1); // Move to next day
todayDate.setHours(0, 0, 0, 0); // Set to start of next day (00:00)
const value: Range = {
from: subDays(todayDate, durationInfo.days),
+1 -7
View File
@@ -7,17 +7,11 @@ export interface WalletStats {
walletType: string;
}
export interface WalletUserStats {
date: string;
newUsers: number;
returningUsers: number;
totalUsers: number;
}
export interface InAppWalletStats {
date: string;
authenticationMethod: string;
uniqueWalletsConnected: number;
newUsers: number;
}
export interface EcosystemWalletStats extends InAppWalletStats {
@@ -40,6 +40,8 @@ export function TeamSidebarLayout(props: {
icon: ChartNoAxesColumnIcon,
label: "Analytics",
},
// ecosystem below here
// TODO: make this one link to an overview page that has a list of all the ecosystems currently deployed
{
links: [
...props.ecosystems.map((ecosystem) => ({
@@ -66,29 +68,28 @@ export function TeamSidebarLayout(props: {
icon: DatabaseIcon,
label: "Usage",
},
...(props.chainSubscriptions.length > 0
? [
{
separator: true,
} as const,
{
links: [
...props.chainSubscriptions.map((chainSubscription) => ({
href: `${layoutPath}/~/infrastructure/${chainSubscription.slug}`,
label: chainSubscription.chainName,
})),
{
href: `${layoutPath}/~/infrastructure/deploy`,
label: "Deploy Infrastructure",
},
],
subMenu: {
icon: WalletCardsIcon,
label: "Chain Infrastucture",
},
},
]
: []),
{
separator: true,
} as const,
// infrastructure below here
// TODO: make this one link to an overview page that has a list of all the chains currently deployed
{
links: [
...props.chainSubscriptions.map((chainSubscription) => ({
href: `${layoutPath}/~/infrastructure/${chainSubscription.slug}`,
label: chainSubscription.chainName,
})),
{
href: `${layoutPath}/~/infrastructure/deploy`,
label: "Deploy Infrastructure",
},
],
subMenu: {
icon: WalletCardsIcon,
label: "Chain Infrastucture",
},
},
]}
footerSidebarLinks={[
{
@@ -1,6 +1,6 @@
import { subDays } from "date-fns";
import { redirect } from "next/navigation";
import { getWalletConnections } from "@/api/analytics";
import { getInAppWalletUsage } from "@/api/analytics";
import { getAuthToken } from "@/api/auth-token";
import { getProjects, type Project } from "@/api/project/projects";
import { getTeamBySlug } from "@/api/team/get-team";
@@ -90,7 +90,8 @@ async function getProjectsWithAnalytics(
const today = new Date();
const thirtyDaysAgo = subDays(today, 30);
const data = await getWalletConnections(
// TODO (stats): also add the external wallet usage?
const data = await getInAppWalletUsage(
{
from: thirtyDaysAgo,
period: "all",
@@ -2,7 +2,7 @@
import { useMemo } from "react";
import { useSetResponsiveSearchParams } from "responsive-rsc";
import type { UniversalBridgeStats, WalletUserStats } from "@/types/analytics";
import type { InAppWalletStats, UniversalBridgeStats } from "@/types/analytics";
import { CombinedBarChartCard } from "../../../../components/Analytics/CombinedBarChartCard";
import { EmptyStateContent } from "../../../../components/Analytics/EmptyStateCard";
@@ -19,7 +19,7 @@ export function TeamHighlightsCard({
selectedChart,
selectedChartQueryParam,
}: {
userStats: WalletUserStats[];
userStats: InAppWalletStats[];
volumeStats: UniversalBridgeStats[];
selectedChart: string | undefined;
selectedChartQueryParam: string;
@@ -32,18 +32,6 @@ export function TeamHighlightsCard({
const chartConfig = {
activeUsers: { color: "hsl(var(--chart-1))", label: "Active Users" },
feesCollected: {
color: "hsl(var(--chart-4))",
emptyContent: (
<EmptyStateContent
description="Your apps haven't collected any fees yet."
link={"https://portal.thirdweb.com/payments"}
metric="Fees"
/>
),
isCurrency: true,
label: "Fee Revenue",
},
newUsers: { color: "hsl(var(--chart-3))", label: "New Users" },
totalVolume: {
color: "hsl(var(--chart-2))",
@@ -57,6 +45,18 @@ export function TeamHighlightsCard({
isCurrency: true,
label: "Total Volume",
},
feesCollected: {
color: "hsl(var(--chart-4))",
emptyContent: (
<EmptyStateContent
description="Your apps haven't collected any fees yet."
link={"https://portal.thirdweb.com/payments"}
metric="Fees"
/>
),
isCurrency: true,
label: "Fee Revenue",
},
} as const;
return (
@@ -96,33 +96,46 @@ type TimeSeriesMetrics = AggregatedMetrics & {
};
function processTimeSeriesData(
userStats: WalletUserStats[],
userStats: InAppWalletStats[],
volumeStats: UniversalBridgeStats[],
): TimeSeriesMetrics[] {
const metrics: TimeSeriesMetrics[] = [];
const dates = [...new Set(userStats.map((a) => a.date))];
for (const date of dates) {
const activeUsers = userStats
.filter(
(u) => new Date(u.date).toISOString() === new Date(date).toISOString(),
)
.reduce((acc, curr) => acc + curr.uniqueWalletsConnected, 0);
const newUsers = userStats
.filter(
(u) => new Date(u.date).toISOString() === new Date(date).toISOString(),
)
.reduce((acc, curr) => acc + curr.newUsers, 0);
for (const stat of userStats) {
const volume = volumeStats
.filter(
(v) =>
new Date(v.date).toISOString() ===
new Date(stat.date).toISOString() && v.status === "completed",
new Date(v.date).toISOString() === new Date(date).toISOString() &&
v.status === "completed",
)
.reduce((acc, curr) => acc + curr.amountUsdCents / 100, 0);
const fees = volumeStats
.filter(
(v) =>
new Date(v.date).toISOString() ===
new Date(stat.date).toISOString() && v.status === "completed",
new Date(v.date).toISOString() === new Date(date).toISOString() &&
v.status === "completed",
)
.reduce((acc, curr) => acc + curr.developerFeeUsdCents / 100, 0);
metrics.push({
activeUsers: stat.totalUsers ?? 0,
date: stat.date,
activeUsers: activeUsers,
date: date,
feesCollected: fees,
newUsers: stat.newUsers ?? 0,
newUsers: newUsers,
totalVolume: volume,
});
}
@@ -13,7 +13,6 @@ import {
getUniversalBridgeUsage,
getUserOpUsage,
getWalletConnections,
getWalletUsers,
} from "@/api/analytics";
import { getAuthToken } from "@/api/auth-token";
import { getTeamBySlug } from "@/api/team/get-team";
@@ -193,7 +192,7 @@ async function AsyncTeamHighlightsCard(props: {
}) {
const [walletUserStatsTimeSeries, universalBridgeUsage] =
await Promise.allSettled([
getWalletUsers(
getInAppWalletUsage(
{
from: props.range.from,
period: props.interval,
@@ -216,7 +215,7 @@ async function AsyncTeamHighlightsCard(props: {
if (
walletUserStatsTimeSeries.status === "fulfilled" &&
universalBridgeUsage.status === "fulfilled" &&
walletUserStatsTimeSeries.value.some((w) => w.totalUsers !== 0)
walletUserStatsTimeSeries.value.some((w) => w.uniqueWalletsConnected !== 0)
) {
return (
<TeamHighlightsCard
@@ -255,8 +254,8 @@ async function AsyncWalletDistributionCard(props: {
<WalletDistributionCard data={walletConnections} />
) : (
<EmptyStateCard
link="https://portal.thirdweb.com/wallets"
metric="Wallets"
link="https://portal.thirdweb.com/wallets/external-wallets"
metric="External Wallets"
/>
);
}
@@ -381,19 +380,17 @@ async function AsyncTotalSponsoredCard(props: {
async function WalletDistributionCard({ data }: { data: WalletStats[] }) {
const formattedData = await Promise.all(
data
.filter((w) => w.walletType !== "smart" && w.walletType !== "smartWallet")
.map(async (w) => {
const wallet = await getWalletInfo(w.walletType as WalletId).catch(
() => ({ name: w.walletType }),
);
return {
totalConnections: w.totalConnections,
uniqueWalletsConnected: w.uniqueWalletsConnected,
walletName: wallet.name,
walletType: w.walletType,
};
}),
data.map(async (w) => {
const wallet = await getWalletInfo(w.walletType as WalletId).catch(
() => ({ name: w.walletType }),
);
return {
totalConnections: w.totalConnections,
uniqueWalletsConnected: w.uniqueWalletsConnected,
walletName: wallet.name,
walletType: w.walletType,
};
}),
);
return (
@@ -404,7 +401,7 @@ async function WalletDistributionCard({ data }: { data: WalletStats[] }) {
value: uniqueWalletsConnected,
};
})}
title="Wallets Connected"
title="External Wallets Connected"
/>
);
}
@@ -54,6 +54,7 @@ function ecosystemWalletStatsStub(
date: formattedDate,
ecosystemPartnerId: "123",
uniqueWalletsConnected: Math.floor(Math.random() * 1000) + 1,
newUsers: Math.floor(Math.random() * 100) + 1,
});
}
}
@@ -2,7 +2,7 @@
import { EmptyStateContent } from "app/(app)/team/components/Analytics/EmptyStateCard";
import { useSetResponsiveSearchParams } from "responsive-rsc";
import type { UniversalBridgeStats, WalletUserStats } from "@/types/analytics";
import type { InAppWalletStats, UniversalBridgeStats } from "@/types/analytics";
import { CombinedBarChartCard } from "../../../../components/Analytics/CombinedBarChartCard";
type AggregatedMetrics = {
@@ -14,7 +14,7 @@ type AggregatedMetrics = {
export function ProjectHighlightsCard(props: {
selectedChart: string | undefined;
userStats: WalletUserStats[];
userStats: InAppWalletStats[];
volumeStats: UniversalBridgeStats[];
teamSlug: string;
projectSlug: string;
@@ -34,18 +34,6 @@ export function ProjectHighlightsCard(props: {
const chartConfig = {
activeUsers: { color: "hsl(var(--chart-1))", label: "Active Users" },
feesCollected: {
color: "hsl(var(--chart-4))",
emptyContent: (
<EmptyStateContent
description="Your app hasn't collected any fees yet."
link={`/team/${teamSlug}/${projectSlug}/payments/settings`}
metric="Fees"
/>
),
isCurrency: true,
label: "Fee Revenue",
},
newUsers: { color: "hsl(var(--chart-3))", label: "New Users" },
totalVolume: {
color: "hsl(var(--chart-2))",
@@ -59,6 +47,18 @@ export function ProjectHighlightsCard(props: {
isCurrency: true,
label: "Total Volume",
},
feesCollected: {
color: "hsl(var(--chart-4))",
emptyContent: (
<EmptyStateContent
description="Your app hasn't collected any fees yet."
link={`/team/${teamSlug}/${projectSlug}/payments/settings`}
metric="Fees"
/>
),
isCurrency: true,
label: "Fee Revenue",
},
} as const;
return (
@@ -101,33 +101,47 @@ type TimeSeriesMetrics = AggregatedMetrics & {
* Processes time series data to combine wallet and user statistics
*/
function processTimeSeriesData(
userStats: WalletUserStats[],
userStats: InAppWalletStats[],
volumeStats: UniversalBridgeStats[],
): TimeSeriesMetrics[] {
const metrics: TimeSeriesMetrics[] = [];
const dates = [
...new Set([
...userStats.map((a) => new Date(a.date).toISOString().slice(0, 10)),
...volumeStats.map((a) => new Date(a.date).toISOString().slice(0, 10)),
]),
];
for (const date of dates) {
const activeUsers = userStats
.filter((u) => new Date(u.date).toISOString().slice(0, 10) === date)
.reduce((acc, curr) => acc + curr.uniqueWalletsConnected, 0);
const newUsers = userStats
.filter((u) => new Date(u.date).toISOString().slice(0, 10) === date)
.reduce((acc, curr) => acc + curr.newUsers, 0);
for (const stat of userStats) {
const volume = volumeStats
.filter(
(v) =>
new Date(v.date).toISOString() ===
new Date(stat.date).toISOString() && v.status === "completed",
new Date(v.date).toISOString().slice(0, 10) === date &&
v.status === "completed",
)
.reduce((acc, curr) => acc + curr.amountUsdCents / 100, 0);
const fees = volumeStats
.filter(
(v) =>
new Date(v.date).toISOString() ===
new Date(stat.date).toISOString() && v.status === "completed",
new Date(v.date).toISOString().slice(0, 10) === date &&
v.status === "completed",
)
.reduce((acc, curr) => acc + curr.developerFeeUsdCents / 100, 0);
metrics.push({
activeUsers: stat.totalUsers ?? 0,
date: stat.date,
activeUsers: activeUsers,
date: date,
feesCollected: fees,
newUsers: stat.newUsers ?? 0,
newUsers: newUsers,
totalVolume: volume,
});
}
@@ -16,7 +16,6 @@ import {
getUniversalBridgeUsage,
getUserOpUsage,
getWalletConnections,
getWalletUsers,
isProjectActive,
} from "@/api/analytics";
import { getAuthToken } from "@/api/auth-token";
@@ -364,7 +363,7 @@ async function AsyncAppHighlightsCard(props: {
}) {
const [walletUserStatsTimeSeries, universalBridgeUsage] =
await Promise.allSettled([
getWalletUsers(
getInAppWalletUsage(
{
from: props.range.from,
period: props.interval,
@@ -389,7 +388,7 @@ async function AsyncAppHighlightsCard(props: {
if (
walletUserStatsTimeSeries.status === "fulfilled" &&
universalBridgeUsage.status === "fulfilled"
)
) {
return (
<div>
<ProjectHighlightsCard
@@ -410,6 +409,7 @@ async function AsyncAppHighlightsCard(props: {
/>
</div>
);
}
return (
<EmptyStateCard
@@ -439,27 +439,25 @@ async function AsyncWalletDistributionCard(props: {
<WalletDistributionCard data={walletConnections} />
) : (
<EmptyStateCard
link="https://portal.thirdweb.com/wallets"
metric="Wallets"
link="https://portal.thirdweb.com/wallets/external-wallets"
metric="External Wallets"
/>
);
}
async function WalletDistributionCard({ data }: { data: WalletStats[] }) {
const formattedData = await Promise.all(
data
.filter((w) => w.walletType !== "smart" && w.walletType !== "smartWallet")
.map(async (w) => {
const wallet = await getWalletInfo(w.walletType as WalletId).catch(
() => ({ name: w.walletType }),
);
return {
totalConnections: w.totalConnections,
uniqueWalletsConnected: w.uniqueWalletsConnected,
walletName: wallet.name,
walletType: w.walletType,
};
}),
data.map(async (w) => {
const wallet = await getWalletInfo(w.walletType as WalletId).catch(
() => ({ name: w.walletType }),
);
return {
totalConnections: w.totalConnections,
uniqueWalletsConnected: w.uniqueWalletsConnected,
walletName: wallet.name,
walletType: w.walletType,
};
}),
);
return (
@@ -470,7 +468,7 @@ async function WalletDistributionCard({ data }: { data: WalletStats[] }) {
value: uniqueWalletsConnected,
};
})}
title="Wallets Connected"
title="External Wallets Connected"
/>
);
}
@@ -120,6 +120,7 @@ function createInAppWalletStatsStub(days: number): InAppWalletStats[] {
authenticationMethod: pickRandomAuthMethod(),
date: new Date(2024, 11, d).toLocaleString(),
uniqueWalletsConnected: uniqueWallets,
newUsers: Math.floor(Math.random() * 100) + 1,
});
if (Math.random() > 0.7) {
@@ -1,48 +1,35 @@
import { subDays } from "date-fns";
import { ActivityIcon, UserIcon } from "lucide-react";
import { Suspense } from "react";
import { getInAppWalletUsage } from "@/api/analytics";
import type { Range } from "@/components/analytics/date-range-selector";
import { StatCard } from "@/components/analytics/stat";
import type { InAppWalletStats } from "@/types/analytics";
function InAppWalletsSummaryInner(props: {
allTimeStats: InAppWalletStats[] | undefined;
monthlyStats: InAppWalletStats[] | undefined;
stats: InAppWalletStats[] | undefined;
isPending: boolean;
}) {
const allTimeStats = props.allTimeStats?.reduce(
(acc, curr) => {
acc.uniqueWalletsConnected += curr.uniqueWalletsConnected;
return acc;
},
{
uniqueWalletsConnected: 0,
},
);
const activeUsers = props.stats?.reduce((acc, curr) => {
return acc + curr.uniqueWalletsConnected;
}, 0);
const monthlyStats = props.monthlyStats?.reduce(
(acc, curr) => {
acc.uniqueWalletsConnected += curr.uniqueWalletsConnected;
return acc;
},
{
uniqueWalletsConnected: 0,
},
);
const newUsers = props.stats?.reduce((acc, curr) => {
return acc + curr.newUsers;
}, 0);
return (
<div className="grid grid-cols-2 gap-4">
<StatCard
icon={ActivityIcon}
isPending={props.isPending}
label="Total Users"
value={allTimeStats?.uniqueWalletsConnected || 0}
label="Active Users"
value={activeUsers || 0}
/>
<StatCard
icon={UserIcon}
isPending={props.isPending}
label="Monthly Active Users"
value={monthlyStats?.uniqueWalletsConnected || 0}
label="New Users"
value={newUsers || 0}
/>
</div>
);
@@ -52,40 +39,26 @@ async function AsyncInAppWalletsSummary(props: {
teamId: string;
projectId: string;
authToken: string;
range: Range;
}) {
const { teamId, projectId, authToken } = props;
const allTimeStatsPromise = getInAppWalletUsage(
const { teamId, projectId, authToken, range } = props;
const aggregatedStatsPromise = getInAppWalletUsage(
{
from: new Date(2022, 0, 1),
from: range.from,
period: "all",
projectId,
teamId,
to: new Date(),
to: range.to,
},
authToken,
);
const monthlyStatsPromise = getInAppWalletUsage(
{
from: subDays(new Date(), 30),
period: "month",
projectId,
teamId,
to: new Date(),
},
authToken,
);
const [allTimeStats, monthlyStats] = await Promise.all([
allTimeStatsPromise,
monthlyStatsPromise,
]).catch(() => [null, null]);
const aggregatedStats = await aggregatedStatsPromise.catch(() => null);
return (
<InAppWalletsSummaryInner
allTimeStats={allTimeStats || undefined}
stats={aggregatedStats || undefined}
isPending={false}
monthlyStats={monthlyStats || undefined}
/>
);
}
@@ -94,21 +67,17 @@ export function InAppWalletsSummary(props: {
teamId: string;
projectId: string;
authToken: string;
range: Range;
}) {
return (
<Suspense
fallback={
<InAppWalletsSummaryInner
allTimeStats={undefined}
isPending={true}
monthlyStats={undefined}
/>
}
fallback={<InAppWalletsSummaryInner stats={undefined} isPending={true} />}
>
<AsyncInAppWalletsSummary
projectId={props.projectId}
teamId={props.teamId}
authToken={props.authToken}
range={props.range}
/>
</Suspense>
);
@@ -40,7 +40,7 @@ type AsyncInAppWalletAnalyticsProps = Omit<
async function AsyncInAppWalletAnalytics(
props: AsyncInAppWalletAnalyticsProps,
) {
const range = props.range ?? getLastNDaysRange("last-120");
const range = props.range ?? getLastNDaysRange("last-30");
const stats = await getInAppWalletUsage(
{
@@ -45,13 +45,14 @@ export default async function Page(props: {
return (
<ResponsiveSearchParamsProvider value={searchParams}>
<div>
<ResponsiveTimeFilters defaultRange={defaultRange} />
<div className="h-6" />
<InAppWalletsSummary
range={range}
projectId={project.id}
teamId={project.teamId}
authToken={authToken}
/>
<div className="h-10" />
<ResponsiveTimeFilters defaultRange={defaultRange} />
<div className="h-6" />
<InAppWalletAnalytics
interval={interval}
@@ -41,7 +41,7 @@ export function useTestWebhook(clientId: string) {
});
const result = await testWebhook(
{ type, webhook_url: webhookUrl },
{ type, webhook_url: webhookUrl, webhook_id: id },
clientId,
);
+14
View File
@@ -1,5 +1,19 @@
# @thirdweb-dev/nebula
## 0.2.37
### Patch Changes
- Updated dependencies [[`1083316`](https://github.com/thirdweb-dev/js/commit/1083316ef681c3f6ca4138acd00b1e945c5156d5)]:
- thirdweb@5.105.37
## 0.2.36
### Patch Changes
- Updated dependencies [[`e01af9d`](https://github.com/thirdweb-dev/js/commit/e01af9db7128a66b8bc7297911f713eb828da3cc)]:
- thirdweb@5.105.36
## 0.2.35
### Patch Changes
+1 -1
View File
@@ -57,5 +57,5 @@
"type": "module",
"types": "./dist/types/exports/thirdweb.d.ts",
"typings": "./dist/types/exports/thirdweb.d.ts",
"version": "0.2.35"
"version": "0.2.37"
}
+12
View File
@@ -1,5 +1,17 @@
# thirdweb
## 5.105.37
### Patch Changes
- [#7872](https://github.com/thirdweb-dev/js/pull/7872) [`1083316`](https://github.com/thirdweb-dev/js/commit/1083316ef681c3f6ca4138acd00b1e945c5156d5) Thanks [@gregfromstl](https://github.com/gregfromstl)! - Update createToken to return a prepared transaction
## 5.105.36
### Patch Changes
- [#7887](https://github.com/thirdweb-dev/js/pull/7887) [`e01af9d`](https://github.com/thirdweb-dev/js/commit/e01af9db7128a66b8bc7297911f713eb828da3cc) Thanks [@leo-shi-dacheng](https://github.com/leo-shi-dacheng)! - fix: #7886
## 5.105.35
### Patch Changes
+1 -1
View File
@@ -417,5 +417,5 @@
}
},
"typings": "./dist/types/exports/thirdweb.d.ts",
"version": "5.105.35"
"version": "5.105.37"
}
@@ -10,7 +10,7 @@ export const mode = /* @__PURE__ */ defineChain({
url: "https://explorer.mode.network/",
},
],
id: 919,
id: 34443,
name: "Mode",
nativeCurrency: { decimals: 18, name: "Ether", symbol: "ETH" },
});
+1 -1
View File
@@ -6,7 +6,7 @@ export {
DEFAULT_DEVELOPER_ADDRESS,
DEFAULT_DEVELOPER_REWARD_BPS,
} from "../tokens/constants.js";
export { createToken } from "../tokens/create-token.js";
export { createToken, prepareCreateToken } from "../tokens/create-token.js";
export { distributeToken } from "../tokens/distribute-token.js";
export {
getDeployedContractFactory,
@@ -62,3 +62,39 @@ export async function createToken(options: CreateTokenOptions) {
return decodedEvent[0]?.args.asset;
}
export async function prepareCreateToken(options: CreateTokenOptions) {
const { client, params, account, launchConfig } = options;
const creator = params.owner || account.address;
const encodedInitData = await encodeInitParams({
client,
creator,
params,
});
const salt: Hex = generateSalt(options.salt || bytesToHex(randomBytes(31)));
const entrypoint = await getDeployedEntrypointERC20(options);
let hookData: Hex = "0x";
let contractId = padHex(toHex("ERC20Asset"), { size: 32 });
if (launchConfig?.kind === "pool") {
hookData = encodePoolConfig(launchConfig.config);
contractId = padHex(toHex("ERC20Asset_Pool"), { size: 32 });
}
const transaction = createById({
contract: entrypoint,
contractId,
params: {
data: encodedInitData,
hookData,
developer: options.developerAddress || DEFAULT_DEVELOPER_ADDRESS,
salt,
},
creator,
});
return transaction;
}
@@ -12,7 +12,7 @@ import {
import type { CreateTokenOptions } from "./types.js";
export async function predictAddress(options: CreateTokenOptions) {
const { client, account, params, launchConfig } = options;
const { client, params, launchConfig, account } = options;
const creator = params.owner || account.address;
const encodedInitData = await encodeInitParams({
+4
View File
@@ -1,5 +1,9 @@
# @thirdweb-dev/wagmi-adapter
## 0.2.134
## 0.2.133
## 0.2.132
## 0.2.131
+1 -1
View File
@@ -55,5 +55,5 @@
"type": "module",
"types": "./dist/types/exports/thirdweb.d.ts",
"typings": "./dist/types/exports/thirdweb.d.ts",
"version": "0.2.132"
"version": "0.2.134"
}