Compare commits
13
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c65022174d | ||
|
|
6818cbabf2 | ||
|
|
a7fb844d87 | ||
|
|
bf431961ec | ||
|
|
c5d4cab8f8 | ||
|
|
1ee0dffec4 | ||
|
|
33611409b0 | ||
|
|
ab55aec10c | ||
|
|
ca22e4659e | ||
|
|
411895c002 | ||
|
|
cfa1c20a91 | ||
|
|
2b16f90715 | ||
|
|
e8892b152f |
@@ -46,12 +46,12 @@
|
||||
"@radix-ui/react-slot": "^1.1.1",
|
||||
"@radix-ui/react-switch": "^1.1.2",
|
||||
"@radix-ui/react-tooltip": "1.1.7",
|
||||
"@sentry/nextjs": "8.51.0",
|
||||
"@sentry/nextjs": "8.52.0",
|
||||
"@shazow/whatsabi": "^0.19.0",
|
||||
"@tanstack/react-query": "5.65.0",
|
||||
"@tanstack/react-query": "5.65.1",
|
||||
"@tanstack/react-table": "^8.20.6",
|
||||
"@thirdweb-dev/service-utils": "workspace:*",
|
||||
"@vercel/functions": "^1.5.2",
|
||||
"@vercel/functions": "^1.6.0",
|
||||
"@vercel/og": "^0.6.5",
|
||||
"abitype": "1.0.8",
|
||||
"chakra-react-select": "^4.7.6",
|
||||
@@ -74,7 +74,7 @@
|
||||
"nextjs-toploader": "^1.6.12",
|
||||
"openapi-types": "^12.1.3",
|
||||
"p-limit": "^6.2.0",
|
||||
"papaparse": "^5.5.1",
|
||||
"papaparse": "^5.5.2",
|
||||
"pluralize": "^8.0.0",
|
||||
"posthog-js": "1.67.1",
|
||||
"qrcode": "^1.5.3",
|
||||
@@ -83,7 +83,7 @@
|
||||
"react-day-picker": "^8.10.1",
|
||||
"react-dom": "19.0.0",
|
||||
"react-dropzone": "^14.3.5",
|
||||
"react-error-boundary": "^4.1.2",
|
||||
"react-error-boundary": "^5.0.0",
|
||||
"react-hook-form": "7.54.2",
|
||||
"react-markdown": "^9.0.1",
|
||||
"react-table": "^7.8.0",
|
||||
@@ -91,9 +91,9 @@
|
||||
"remark-gfm": "^4.0.0",
|
||||
"server-only": "^0.0.1",
|
||||
"shiki": "1.27.0",
|
||||
"sonner": "^1.7.2",
|
||||
"sonner": "^1.7.3",
|
||||
"spdx-correct": "^3.2.0",
|
||||
"swagger-ui-react": "^5.18.2",
|
||||
"swagger-ui-react": "^5.18.3",
|
||||
"tailwind-merge": "^2.6.0",
|
||||
"tailwindcss-animate": "^1.0.7",
|
||||
"thirdweb": "workspace:*",
|
||||
@@ -129,12 +129,12 @@
|
||||
"@typescript-eslint/eslint-plugin": "7.14.1",
|
||||
"@typescript-eslint/parser": "7.14.1",
|
||||
"autoprefixer": "^10.4.19",
|
||||
"checkly": "^4.18.0",
|
||||
"checkly": "^4.19.1",
|
||||
"eslint": "8.57.0",
|
||||
"eslint-config-biome": "1.9.4",
|
||||
"eslint-plugin-react-compiler": "19.0.0-beta-df7b47d-20241124",
|
||||
"eslint-plugin-storybook": "^0.11.1",
|
||||
"knip": "5.43.5",
|
||||
"knip": "5.43.6",
|
||||
"next-sitemap": "^4.2.3",
|
||||
"postcss": "8.5.1",
|
||||
"storybook": "8.5.2",
|
||||
|
||||
@@ -8,7 +8,7 @@ import {
|
||||
import { useThirdwebClient } from "@/constants/thirdweb.client";
|
||||
import { resolveSchemeWithErrorHandler } from "@/lib/resolveSchemeWithErrorHandler";
|
||||
import { useClipboard } from "hooks/useClipboard";
|
||||
import { Check, Copy, ExternalLinkIcon } from "lucide-react";
|
||||
import { Check, Copy } from "lucide-react";
|
||||
import { useMemo } from "react";
|
||||
import { type ThirdwebClient, isAddress } from "thirdweb";
|
||||
import { ZERO_ADDRESS } from "thirdweb";
|
||||
@@ -148,21 +148,6 @@ export function WalletAddress(props: {
|
||||
);
|
||||
})
|
||||
)}
|
||||
<Button
|
||||
asChild
|
||||
variant="upsell"
|
||||
className="flex flex-row items-center gap-2 text-sm"
|
||||
size="sm"
|
||||
>
|
||||
<a
|
||||
target="_blank"
|
||||
href="https://blog.thirdweb.com/changelog/introducing-the-social-sdk?ref=dashboard-social-wallet"
|
||||
rel="noreferrer"
|
||||
>
|
||||
Learn more
|
||||
<ExternalLinkIcon className="size-4" />
|
||||
</a>
|
||||
</Button>
|
||||
</div>
|
||||
</HoverCardContent>
|
||||
</HoverCard>
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@abstract-foundation/agw-client": "^1.3.0",
|
||||
"@abstract-foundation/agw-react": "^1.4.2",
|
||||
"@abstract-foundation/agw-react": "^1.4.3",
|
||||
"@radix-ui/react-accordion": "^1.2.2",
|
||||
"@radix-ui/react-checkbox": "^1.1.3",
|
||||
"@radix-ui/react-dialog": "1.1.5",
|
||||
@@ -29,7 +29,7 @@
|
||||
"@radix-ui/react-switch": "^1.1.2",
|
||||
"@radix-ui/react-tabs": "^1.1.2",
|
||||
"@radix-ui/react-tooltip": "1.1.7",
|
||||
"@tanstack/react-query": "5.65.0",
|
||||
"@tanstack/react-query": "5.65.1",
|
||||
"@thirdweb-dev/engine": "^0.0.18",
|
||||
"class-variance-authority": "^0.7.1",
|
||||
"clsx": "^2.1.1",
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
"@radix-ui/react-select": "^2.1.5",
|
||||
"@radix-ui/react-slot": "^1.1.1",
|
||||
"@radix-ui/react-tabs": "^1.1.2",
|
||||
"@tanstack/react-query": "5.65.0",
|
||||
"@tanstack/react-query": "5.65.1",
|
||||
"@tryghost/content-api": "^1.11.21",
|
||||
"class-variance-authority": "^0.7.1",
|
||||
"clsx": "^2.1.1",
|
||||
@@ -69,7 +69,7 @@
|
||||
"eslint-plugin-mdx": "^3.1.5",
|
||||
"eslint-plugin-svg-jsx": "^1.2.4",
|
||||
"eslint-plugin-tailwindcss": "^3.18.0",
|
||||
"knip": "5.43.5",
|
||||
"knip": "5.43.6",
|
||||
"next-sitemap": "^4.2.3",
|
||||
"postcss": "8.5.1",
|
||||
"tailwindcss": "3.4.17",
|
||||
|
||||
@@ -4,6 +4,11 @@
|
||||
|
||||
We are rolling out Nebula approval in batches daily - stay tuned!
|
||||
|
||||
### Which contracts does Nebula support?
|
||||
Nebula supports the read and write context of any verified contract or any contract on the thirdweb dashboard. For deploying through Nebula, supported contracts include [Token - ERC20](https://thirdweb.com/thirdweb.eth/TokenERC20), [NFT Collection - ERC721](https://thirdweb.com/thirdweb.eth/TokenERC721), [Edition - ERC1155](https://thirdweb.com/thirdweb.eth/TokenERC1155), and [Split](https://thirdweb.com/thirdweb.eth/Split) contracts.
|
||||
|
||||
If you have a published contract you would like to enable for deployment through Nebula, please [contact us](https://thirdweb.com/contact-us).
|
||||
|
||||
### Does Nebula have memory from past conversations?
|
||||
Nebula retains memory within the confines of a session.
|
||||
|
||||
@@ -16,4 +21,4 @@ Nebula is not currently open source. We are exploring open sourcing Nebula in th
|
||||
|
||||
### When will pricing be available for Nebula?
|
||||
|
||||
Pricing options will be available in beta. Nebula is still being tested in alpha.
|
||||
Pricing options will be available in beta. Nebula is still being tested in alpha.
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
# OpenAI
|
||||
|
||||
### Chat Completions API
|
||||
|
||||
Compatible with OpenAI’s Chat Completion API to process chat history and generate context-aware responses.
|
||||
|
||||
```python
|
||||
from openai import OpenAI
|
||||
|
||||
client = OpenAI(
|
||||
base_url="https://nebula-api.thirdweb.com",
|
||||
api_key="{{THIRDWEB_SECRET_KEY}}",
|
||||
)
|
||||
chat_completion = client.chat.completions.create(
|
||||
model="t0",
|
||||
messages=[{"role": "user", "content": "Hello Nebula!"}],
|
||||
stream=False,
|
||||
extra_body={ "context": { "wallet_address": "0x..." }}
|
||||
)
|
||||
|
||||
print(chat_completion)
|
||||
```
|
||||
|
||||
### Models API
|
||||
|
||||
Compatible with OpenAI’s Models API to list out models used.
|
||||
|
||||
```python
|
||||
from openai import OpenAI
|
||||
|
||||
# https://nebula-api.thirdweb.com/models
|
||||
|
||||
client = OpenAI(
|
||||
base_url="https://nebula-api.thirdweb.com/",
|
||||
api_key="",
|
||||
)
|
||||
|
||||
models = client.models.list()
|
||||
print(models)
|
||||
```
|
||||
@@ -2,11 +2,7 @@ import { Callout } from '@doc'
|
||||
|
||||
# Plugins
|
||||
|
||||
- [OpenAI](/nebula/plugins/openai)
|
||||
- [Eliza](/nebula/plugins/eliza)
|
||||
|
||||
<Callout variant='info' title='Coming Soon'>
|
||||
|
||||
We are actively developing plugins to develop with other frameworks and languages.
|
||||
|
||||
If you have a specific request, please [contact us](https://thirdweb.com/contact).
|
||||
|
||||
</Callout>
|
||||
We are actively adding more integrations, for any specific requests please [contact us](https://thirdweb.com/contact).
|
||||
@@ -110,10 +110,14 @@ export const sidebar: SideBar = {
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Plugins",
|
||||
name: "Plugins & Integrations",
|
||||
href: "/nebula/plugins",
|
||||
icon: <Blocks />,
|
||||
links: [
|
||||
{
|
||||
name: "OpenAI",
|
||||
href: "/nebula/plugins/openai",
|
||||
},
|
||||
{
|
||||
name: "Eliza",
|
||||
href: "/nebula/plugins/eliza",
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
"@radix-ui/react-label": "^2.1.1",
|
||||
"@radix-ui/react-popover": "^1.1.5",
|
||||
"@radix-ui/react-slot": "^1.1.1",
|
||||
"@tanstack/react-query": "5.65.0",
|
||||
"@tanstack/react-query": "5.65.1",
|
||||
"class-variance-authority": "^0.7.1",
|
||||
"clsx": "^2.1.1",
|
||||
"cmdk": "^1.0.4",
|
||||
@@ -26,7 +26,7 @@
|
||||
"react-dom": "19.0.0",
|
||||
"react-hook-form": "7.54.2",
|
||||
"server-only": "^0.0.1",
|
||||
"sonner": "^1.7.2",
|
||||
"sonner": "^1.7.3",
|
||||
"tailwind-merge": "^2.6.0",
|
||||
"tailwindcss-animate": "^1.0.7",
|
||||
"thirdweb": "workspace:*",
|
||||
@@ -43,7 +43,7 @@
|
||||
"eslint": "8.57.0",
|
||||
"eslint-config-biome": "1.9.4",
|
||||
"eslint-plugin-react-compiler": "19.0.0-beta-df7b47d-20241124",
|
||||
"knip": "5.43.5",
|
||||
"knip": "5.43.6",
|
||||
"postcss": "8.5.1",
|
||||
"postcss-load-config": "^6.0.1",
|
||||
"tailwindcss": "3.4.17",
|
||||
|
||||
@@ -1,5 +1,29 @@
|
||||
# @thirdweb-dev/service-utils
|
||||
|
||||
## 0.8.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#6113](https://github.com/thirdweb-dev/js/pull/6113) [`6818cba`](https://github.com/thirdweb-dev/js/commit/6818cbabf25ce73d09dfc971ae793cd9844ceca7) Thanks [@arcoraven](https://github.com/arcoraven)! - Change UsageV2 to per-product topics
|
||||
|
||||
## 0.8.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#6106](https://github.com/thirdweb-dev/js/pull/6106) [`3361140`](https://github.com/thirdweb-dev/js/commit/33611409b0efd58803be4a96194f5872ddf4bde0) Thanks [@jnsdls](https://github.com/jnsdls)! - updated dependencies
|
||||
|
||||
## 0.8.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
- [#6101](https://github.com/thirdweb-dev/js/pull/6101) [`e8892b1`](https://github.com/thirdweb-dev/js/commit/e8892b152f70d3024dfbefcddcfa74a69a12bdd0) Thanks [@jnsdls](https://github.com/jnsdls)! - pass `team` instead of `project` to `rateLimit`
|
||||
|
||||
## 0.7.3
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#6084](https://github.com/thirdweb-dev/js/pull/6084) [`b5e327e`](https://github.com/thirdweb-dev/js/commit/b5e327e5ec745ce1beb9a79404fa5b11d0c5588e) Thanks [@jnsdls](https://github.com/jnsdls)! - add `billingPlanVersion` to `TeamResponse`
|
||||
|
||||
## 0.7.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@thirdweb-dev/service-utils",
|
||||
"version": "0.7.2",
|
||||
"version": "0.8.2",
|
||||
"type": "module",
|
||||
"main": "dist/cjs/index.js",
|
||||
"module": "dist/esm/index.js",
|
||||
@@ -50,7 +50,7 @@
|
||||
"zod": "3.24.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@cloudflare/workers-types": "4.20250124.3",
|
||||
"@cloudflare/workers-types": "4.20250129.0",
|
||||
"@types/node": "22.10.10",
|
||||
"typescript": "5.7.3",
|
||||
"vitest": "3.0.4"
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import type { UsageV2Event } from "../core/usageV2.js";
|
||||
import type { ServiceName } from "../core/services.js";
|
||||
import { type UsageV2Event, getTopicName } from "../core/usageV2.js";
|
||||
|
||||
/**
|
||||
* Send events to Kafka.
|
||||
@@ -19,6 +20,7 @@ export async function sendUsageV2Events(
|
||||
events: UsageV2Event[],
|
||||
options: {
|
||||
environment: "development" | "production";
|
||||
productName: ServiceName;
|
||||
serviceKey: string;
|
||||
},
|
||||
): Promise<void> {
|
||||
@@ -27,7 +29,8 @@ export async function sendUsageV2Events(
|
||||
? "https://u.thirdweb.com"
|
||||
: "https://u.thirdweb-dev.com";
|
||||
|
||||
const resp = await fetch(`${baseUrl}/usage-v2/raw-events`, {
|
||||
const topic = getTopicName(options.productName);
|
||||
const resp = await fetch(`${baseUrl}/usage-v2/${topic}`, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
|
||||
@@ -45,6 +45,7 @@ export type TeamResponse = {
|
||||
slug: string;
|
||||
image: string | null;
|
||||
billingPlan: "free" | "starter" | "growth" | "pro";
|
||||
billingPlanVersion: number;
|
||||
createdAt: Date;
|
||||
updatedAt: Date | null;
|
||||
billingEmail: string | null;
|
||||
@@ -163,24 +164,3 @@ export async function fetchTeamAndProject(
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export async function updateRateLimitedAt(
|
||||
projectId: string,
|
||||
config: CoreServiceConfig,
|
||||
): Promise<void> {
|
||||
const { apiUrl, serviceScope: scope, serviceApiKey } = config;
|
||||
|
||||
const url = `${apiUrl}/usage/rateLimit`;
|
||||
|
||||
await fetch(url, {
|
||||
method: "PUT",
|
||||
headers: {
|
||||
"x-service-api-key": serviceApiKey,
|
||||
"content-type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
apiKeyId: projectId, // projectId is the apiKeyId
|
||||
scope,
|
||||
}),
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,8 +1,4 @@
|
||||
import {
|
||||
type CoreServiceConfig,
|
||||
type ProjectResponse,
|
||||
updateRateLimitedAt,
|
||||
} from "../api.js";
|
||||
import type { CoreServiceConfig, TeamResponse } from "../api.js";
|
||||
import type { RateLimitResult } from "./types.js";
|
||||
|
||||
const RATE_LIMIT_WINDOW_SECONDS = 10;
|
||||
@@ -14,7 +10,7 @@ type IRedis = {
|
||||
};
|
||||
|
||||
export async function rateLimit(args: {
|
||||
project?: ProjectResponse;
|
||||
team: TeamResponse;
|
||||
limitPerSecond: number;
|
||||
serviceConfig: CoreServiceConfig;
|
||||
redis: IRedis;
|
||||
@@ -25,13 +21,7 @@ export async function rateLimit(args: {
|
||||
*/
|
||||
sampleRate?: number;
|
||||
}): Promise<RateLimitResult> {
|
||||
const {
|
||||
project,
|
||||
limitPerSecond,
|
||||
serviceConfig,
|
||||
redis,
|
||||
sampleRate = 1.0,
|
||||
} = args;
|
||||
const { team, limitPerSecond, serviceConfig, redis, sampleRate = 1.0 } = args;
|
||||
|
||||
const shouldSampleRequest = Math.random() < sampleRate;
|
||||
if (!shouldSampleRequest) {
|
||||
@@ -57,7 +47,7 @@ export async function rateLimit(args: {
|
||||
const timestampWindow =
|
||||
Math.floor(Date.now() / (1000 * RATE_LIMIT_WINDOW_SECONDS)) *
|
||||
RATE_LIMIT_WINDOW_SECONDS;
|
||||
const key = `rate-limit:${serviceScope}:${project?.id}:${timestampWindow}`;
|
||||
const key = `rate-limit:${serviceScope}:${team.id}:${timestampWindow}`;
|
||||
|
||||
// Increment and get the current request count in this window.
|
||||
const requestCount = await redis.incr(key);
|
||||
@@ -71,17 +61,6 @@ export async function rateLimit(args: {
|
||||
limitPerSecond * sampleRate * RATE_LIMIT_WINDOW_SECONDS;
|
||||
|
||||
if (requestCount > limitPerWindow) {
|
||||
/**
|
||||
* Report rate limit hits.
|
||||
* Only track rate limit when its hit for the first time.
|
||||
* Not waiting for tracking to complete as user doesn't need to wait.
|
||||
*/
|
||||
if (requestCount === limitPerWindow + 1 && project?.id) {
|
||||
updateRateLimitedAt(project.id, serviceConfig).catch(() => {
|
||||
// no-op
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
rateLimited: true,
|
||||
requestCount,
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { validProjectResponse, validServiceConfig } from "../../mocks.js";
|
||||
import { updateRateLimitedAt } from "../api.js";
|
||||
import { validServiceConfig, validTeamResponse } from "../../mocks.js";
|
||||
import { rateLimit } from "./index.js";
|
||||
|
||||
const mockRedis = {
|
||||
@@ -8,11 +7,6 @@ const mockRedis = {
|
||||
expire: vi.fn(),
|
||||
};
|
||||
|
||||
// Mocking the updateRateLimitedAt function
|
||||
vi.mock("../../../src/core/api", () => ({
|
||||
updateRateLimitedAt: vi.fn().mockResolvedValue({}),
|
||||
}));
|
||||
|
||||
describe("rateLimit", () => {
|
||||
beforeEach(() => {
|
||||
// Clear mock function calls and reset any necessary state.
|
||||
@@ -27,7 +21,7 @@ describe("rateLimit", () => {
|
||||
|
||||
it("should not rate limit if service scope is not in rate limits", async () => {
|
||||
const result = await rateLimit({
|
||||
project: validProjectResponse,
|
||||
team: validTeamResponse,
|
||||
limitPerSecond: 0,
|
||||
serviceConfig: validServiceConfig,
|
||||
redis: mockRedis,
|
||||
@@ -44,7 +38,7 @@ describe("rateLimit", () => {
|
||||
mockRedis.incr.mockResolvedValue(50); // Current count is 50 requests in 10 seconds.
|
||||
|
||||
const result = await rateLimit({
|
||||
project: validProjectResponse,
|
||||
team: validTeamResponse,
|
||||
limitPerSecond: 5,
|
||||
serviceConfig: validServiceConfig,
|
||||
redis: mockRedis,
|
||||
@@ -55,7 +49,7 @@ describe("rateLimit", () => {
|
||||
requestCount: 50,
|
||||
rateLimit: 50,
|
||||
});
|
||||
expect(updateRateLimitedAt).not.toHaveBeenCalled();
|
||||
|
||||
expect(mockRedis.expire).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
@@ -63,7 +57,7 @@ describe("rateLimit", () => {
|
||||
mockRedis.incr.mockResolvedValue(51);
|
||||
|
||||
const result = await rateLimit({
|
||||
project: validProjectResponse,
|
||||
team: validTeamResponse,
|
||||
limitPerSecond: 5,
|
||||
serviceConfig: validServiceConfig,
|
||||
redis: mockRedis,
|
||||
@@ -77,7 +71,7 @@ describe("rateLimit", () => {
|
||||
errorMessage: `You've exceeded your storage rate limit at 5 reqs/sec. To get higher rate limits, contact us at https://thirdweb.com/contact-us.`,
|
||||
errorCode: "RATE_LIMIT_EXCEEDED",
|
||||
});
|
||||
expect(updateRateLimitedAt).toHaveBeenCalled();
|
||||
|
||||
expect(mockRedis.expire).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
@@ -85,7 +79,7 @@ describe("rateLimit", () => {
|
||||
mockRedis.incr.mockResolvedValue(1);
|
||||
|
||||
const result = await rateLimit({
|
||||
project: validProjectResponse,
|
||||
team: validTeamResponse,
|
||||
limitPerSecond: 5,
|
||||
serviceConfig: validServiceConfig,
|
||||
redis: mockRedis,
|
||||
@@ -104,7 +98,7 @@ describe("rateLimit", () => {
|
||||
vi.spyOn(global.Math, "random").mockReturnValue(0.08);
|
||||
|
||||
const result = await rateLimit({
|
||||
project: validProjectResponse,
|
||||
team: validTeamResponse,
|
||||
limitPerSecond: 5,
|
||||
serviceConfig: validServiceConfig,
|
||||
redis: mockRedis,
|
||||
@@ -127,7 +121,7 @@ describe("rateLimit", () => {
|
||||
vi.spyOn(global.Math, "random").mockReturnValue(0.15);
|
||||
|
||||
const result = await rateLimit({
|
||||
project: validProjectResponse,
|
||||
team: validTeamResponse,
|
||||
limitPerSecond: 5,
|
||||
serviceConfig: validServiceConfig,
|
||||
redis: mockRedis,
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import type { ServiceName } from "../node/index.js";
|
||||
|
||||
export interface UsageV2Event {
|
||||
/**
|
||||
* A unique identifier for the event. Defaults to a random UUID.
|
||||
@@ -8,10 +10,6 @@ export interface UsageV2Event {
|
||||
* The event timestamp. Defaults to now().
|
||||
*/
|
||||
created_at?: Date;
|
||||
/**
|
||||
* The source of the event. Example: "storage"
|
||||
*/
|
||||
source: string;
|
||||
/**
|
||||
* The action of the event. Example: "upload"
|
||||
*/
|
||||
@@ -49,8 +47,12 @@ export interface UsageV2Event {
|
||||
*/
|
||||
product_version?: string;
|
||||
/**
|
||||
* An object of service-specific data. Example: "file_size_bytes"
|
||||
* It is safe to pass any new JSON-serializable data here before updating the usageV2 schema.
|
||||
* An object of arbitrary key-value pairs.
|
||||
* Values can be boolean, number, string, Date, or null.
|
||||
*/
|
||||
data: Record<string, unknown>;
|
||||
[key: string]: boolean | number | string | Date | null | undefined;
|
||||
}
|
||||
|
||||
export function getTopicName(productName: ServiceName) {
|
||||
return `usage_v2.raw_${productName}`;
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ export type {
|
||||
TeamResponse,
|
||||
} from "./core/api.js";
|
||||
|
||||
export { fetchTeamAndProject, updateRateLimitedAt } from "./core/api.js";
|
||||
export { fetchTeamAndProject } from "./core/api.js";
|
||||
|
||||
export {
|
||||
authorizeBundleId,
|
||||
|
||||
@@ -42,6 +42,7 @@ export const validTeamResponse: TeamResponse = {
|
||||
createdAt: new Date("2024-06-01"),
|
||||
updatedAt: new Date("2024-06-01"),
|
||||
billingPlan: "free",
|
||||
billingPlanVersion: 1,
|
||||
billingEmail: "[email protected]",
|
||||
billingStatus: "noPayment",
|
||||
growthTrialEligible: false,
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
import { randomUUID } from "node:crypto";
|
||||
import { checkServerIdentity } from "node:tls";
|
||||
import { Kafka, type Producer } from "kafkajs";
|
||||
import type { UsageV2Event } from "../core/usageV2.js";
|
||||
|
||||
const TOPIC_USAGE_V2 = "usage_v2.raw_events";
|
||||
import type { ServiceName } from "../core/services.js";
|
||||
import { type UsageV2Event, getTopicName } from "../core/usageV2.js";
|
||||
|
||||
/**
|
||||
* Creates a UsageV2Producer which opens a persistent TCP connection.
|
||||
@@ -21,6 +20,7 @@ const TOPIC_USAGE_V2 = "usage_v2.raw_events";
|
||||
export class UsageV2Producer {
|
||||
private kafka: Kafka;
|
||||
private producer: Producer | null = null;
|
||||
private topic: string;
|
||||
|
||||
constructor(config: {
|
||||
/**
|
||||
@@ -31,6 +31,10 @@ export class UsageV2Producer {
|
||||
* The environment the service is running in.
|
||||
*/
|
||||
environment: "development" | "production";
|
||||
/**
|
||||
* The product "source" where usage is coming from.
|
||||
*/
|
||||
productName: ServiceName;
|
||||
|
||||
username: string;
|
||||
password: string;
|
||||
@@ -52,6 +56,8 @@ export class UsageV2Producer {
|
||||
password: config.password,
|
||||
},
|
||||
});
|
||||
|
||||
this.topic = getTopicName(config.productName);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -82,27 +88,18 @@ export class UsageV2Producer {
|
||||
|
||||
const parsedEvents = events.map((event) => {
|
||||
return {
|
||||
...event,
|
||||
id: event.id ?? randomUUID(),
|
||||
created_at: event.created_at ?? new Date(),
|
||||
source: event.source,
|
||||
action: event.action,
|
||||
// Remove the "team_" prefix, if any.
|
||||
team_id: event.team_id.startsWith("team_")
|
||||
? event.team_id.slice(5)
|
||||
: event.team_id,
|
||||
project_id: event.project_id,
|
||||
sdk_name: event.sdk_name,
|
||||
sdk_platform: event.sdk_platform,
|
||||
sdk_version: event.sdk_version,
|
||||
sdk_os: event.sdk_os,
|
||||
product_name: event.product_name,
|
||||
product_version: event.product_version,
|
||||
data: JSON.stringify(event.data),
|
||||
};
|
||||
});
|
||||
|
||||
await this.producer.send({
|
||||
topic: TOPIC_USAGE_V2,
|
||||
topic: this.topic,
|
||||
messages: parsedEvents.map((event) => ({
|
||||
value: JSON.stringify(event),
|
||||
})),
|
||||
|
||||
@@ -1,5 +1,19 @@
|
||||
# thirdweb
|
||||
|
||||
## 5.87.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#6104](https://github.com/thirdweb-dev/js/pull/6104) [`bf43196`](https://github.com/thirdweb-dev/js/commit/bf431961ec685deefc0089b8d644c35f849fbf86) Thanks [@MananTank](https://github.com/MananTank)! - Fix thirdweb Pay Modal logging react-query error when opened
|
||||
|
||||
## 5.87.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#6106](https://github.com/thirdweb-dev/js/pull/6106) [`3361140`](https://github.com/thirdweb-dev/js/commit/33611409b0efd58803be4a96194f5872ddf4bde0) Thanks [@jnsdls](https://github.com/jnsdls)! - updated dependencies
|
||||
|
||||
- [#6105](https://github.com/thirdweb-dev/js/pull/6105) [`ab55aec`](https://github.com/thirdweb-dev/js/commit/ab55aec10ccb078add40bd774d157bc0f19ab0bf) Thanks [@joaquim-verges](https://github.com/joaquim-verges)! - Allow connecting wallets without setting them as active with useConnect
|
||||
|
||||
## 5.87.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "thirdweb",
|
||||
"version": "5.87.0",
|
||||
"version": "5.87.2",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/thirdweb-dev/js.git#main"
|
||||
@@ -218,7 +218,7 @@
|
||||
"@radix-ui/react-focus-scope": "1.1.1",
|
||||
"@radix-ui/react-icons": "1.3.2",
|
||||
"@radix-ui/react-tooltip": "1.1.7",
|
||||
"@tanstack/react-query": "5.65.0",
|
||||
"@tanstack/react-query": "5.65.1",
|
||||
"@walletconnect/ethereum-provider": "2.17.5",
|
||||
"@walletconnect/sign-client": "2.17.5",
|
||||
"abitype": "1.0.8",
|
||||
@@ -228,7 +228,7 @@
|
||||
"mipd": "0.0.7",
|
||||
"ox": "0.6.9",
|
||||
"uqr": "0.1.2",
|
||||
"viem": "2.22.15"
|
||||
"viem": "2.22.17"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@aws-sdk/client-lambda": "^3",
|
||||
@@ -362,7 +362,7 @@
|
||||
"expo-linking": "7.0.3",
|
||||
"expo-web-browser": "14.0.1",
|
||||
"happy-dom": "16.7.3",
|
||||
"knip": "5.43.5",
|
||||
"knip": "5.43.6",
|
||||
"msw": "2.7.0",
|
||||
"prettier": "3.3.3",
|
||||
"react": "19.0.0",
|
||||
|
||||
@@ -83,7 +83,7 @@ export function prepareDirectDeployTransaction(
|
||||
* ## Deploying a regular contract from ABI and bytecode
|
||||
*
|
||||
* ```ts
|
||||
* import { deployContract } from "thirdweb/deployContract";
|
||||
* import { deployContract } from "thirdweb/deploys";
|
||||
*
|
||||
* const address = await deployContract({
|
||||
* client,
|
||||
@@ -101,7 +101,7 @@ export function prepareDirectDeployTransaction(
|
||||
* ## Deploying a contract deterministically
|
||||
*
|
||||
* ```ts
|
||||
* import { deployContract } from "thirdweb/deployContract";
|
||||
* import { deployContract } from "thirdweb/deploys";
|
||||
*
|
||||
* const address = await deployContract({
|
||||
* client,
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
import type React from "react";
|
||||
import { createContext, useContext } from "react";
|
||||
import type { ThirdwebClient } from "../../../client/client.js";
|
||||
import { isAddress } from "../../../utils/address.js";
|
||||
/**
|
||||
* Props for the <AccountProvider /> component
|
||||
* @component
|
||||
@@ -53,9 +52,6 @@ export function AccountProvider(
|
||||
"AccountProvider: No address passed. Ensure an address is always provided to the AccountProvider",
|
||||
);
|
||||
}
|
||||
if (!isAddress(props.address)) {
|
||||
throw new Error(`AccountProvider: Invalid address: ${props.address}`);
|
||||
}
|
||||
return (
|
||||
<AccountProviderContext.Provider value={props}>
|
||||
{props.children}
|
||||
|
||||
@@ -24,7 +24,7 @@ export function useWalletName(props: {
|
||||
/**
|
||||
* @internal Exported for tests only
|
||||
*/
|
||||
function getQueryKeys(props: {
|
||||
export function getQueryKeys(props: {
|
||||
id: WalletId;
|
||||
formatFn?: (str: string) => string;
|
||||
}) {
|
||||
@@ -41,7 +41,7 @@ function getQueryKeys(props: {
|
||||
/**
|
||||
* @internal Exported for tests only
|
||||
*/
|
||||
async function fetchWalletName(props: {
|
||||
export async function fetchWalletName(props: {
|
||||
id: WalletId;
|
||||
formatFn?: (str: string) => string;
|
||||
}) {
|
||||
|
||||
@@ -37,7 +37,9 @@ export function TransactionModal(props: ModalProps) {
|
||||
useQuery({
|
||||
queryKey: ["transaction-modal-event"],
|
||||
queryFn: () => {
|
||||
if (!account || !wallet) return;
|
||||
if (!account || !wallet) {
|
||||
throw new Error(); // never happens, because enabled is false
|
||||
}
|
||||
trackPayEvent({
|
||||
client: props.client,
|
||||
walletAddress: account.address,
|
||||
@@ -45,8 +47,10 @@ export function TransactionModal(props: ModalProps) {
|
||||
dstChainId: props.tx.chain.id,
|
||||
event: "open_pay_transaction_modal",
|
||||
});
|
||||
|
||||
return null;
|
||||
},
|
||||
enabled: !!wallet,
|
||||
enabled: !!wallet && !!account,
|
||||
});
|
||||
|
||||
return (
|
||||
|
||||
@@ -24,6 +24,7 @@ export type ConnectionManager = ReturnType<typeof createConnectionManager>;
|
||||
export type ConnectManagerOptions = {
|
||||
client: ThirdwebClient;
|
||||
accountAbstraction?: SmartWalletOptions;
|
||||
setWalletAsActive?: boolean;
|
||||
onConnect?: (wallet: Wallet) => void;
|
||||
};
|
||||
|
||||
@@ -146,7 +147,9 @@ export function createConnectionManager(storage: AsyncStorage) {
|
||||
// add personal wallet to connected wallets list even if it's not the active one
|
||||
addConnectedWallet(wallet);
|
||||
|
||||
handleSetActiveWallet(activeWallet);
|
||||
if (options?.setWalletAsActive !== false) {
|
||||
handleSetActiveWallet(activeWallet);
|
||||
}
|
||||
|
||||
wallet.subscribe("accountChanged", async () => {
|
||||
// We reimplement connect here to prevent memory leaks
|
||||
|
||||
@@ -1,5 +1,15 @@
|
||||
# @thirdweb-dev/wagmi-adapter
|
||||
|
||||
## 0.2.10
|
||||
|
||||
## 0.2.9
|
||||
|
||||
## 0.2.8
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#6100](https://github.com/thirdweb-dev/js/pull/6100) [`411895c`](https://github.com/thirdweb-dev/js/commit/411895c0027200fc580fcd58a2ac440da6e227a0) Thanks [@gregfromstl](https://github.com/gregfromstl)! - Fix wagmi adapter usage with account factories
|
||||
|
||||
## 0.2.7
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@thirdweb-dev/wagmi-adapter",
|
||||
"version": "0.2.7",
|
||||
"version": "0.2.10",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/thirdweb-dev/js.git#main"
|
||||
|
||||
@@ -95,9 +95,10 @@ export function inAppWalletConnector(
|
||||
const lastChainId = await config.storage?.getItem("tw.lastChainId");
|
||||
if (params?.isReconnecting) {
|
||||
const { autoConnect } = await import("thirdweb/wallets");
|
||||
const chainId = lastChainId || args.smartAccount?.chain?.id || 1;
|
||||
await autoConnect({
|
||||
client,
|
||||
chain: defineChain(lastChainId || 1),
|
||||
chain: defineChain(chainId),
|
||||
wallets: [wallet],
|
||||
});
|
||||
|
||||
@@ -108,7 +109,7 @@ export function inAppWalletConnector(
|
||||
|
||||
return {
|
||||
accounts: [getAddress(account.address)],
|
||||
chainId: lastChainId || 1,
|
||||
chainId: chainId,
|
||||
};
|
||||
}
|
||||
const inAppOptions = params && "strategy" in params ? params : undefined;
|
||||
@@ -117,7 +118,12 @@ export function inAppWalletConnector(
|
||||
"Missing strategy prop, pass it to connect() when connecting to this connector",
|
||||
);
|
||||
}
|
||||
const chain = defineChain(inAppOptions?.chainId || lastChainId || 1);
|
||||
const chain = defineChain(
|
||||
inAppOptions?.chainId ||
|
||||
lastChainId ||
|
||||
args.smartAccount?.chain?.id ||
|
||||
1,
|
||||
);
|
||||
const decoratedOptions = {
|
||||
...inAppOptions,
|
||||
client,
|
||||
|
||||
Generated
+824
-623
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user