thirdweb 5.71.0 → 5.72.0-nightly-a98550d229e7fd124e1977fcc64dbd1b602ce656-20241126000403

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/dist/cjs/exports/react.js +8 -1
  2. package/dist/cjs/exports/react.js.map +1 -1
  3. package/dist/cjs/react/web/ui/prebuilt/Chain/icon.js +96 -0
  4. package/dist/cjs/react/web/ui/prebuilt/Chain/icon.js.map +1 -0
  5. package/dist/cjs/react/web/ui/prebuilt/Chain/name.js +124 -0
  6. package/dist/cjs/react/web/ui/prebuilt/Chain/name.js.map +1 -0
  7. package/dist/cjs/react/web/ui/prebuilt/Chain/provider.js +54 -0
  8. package/dist/cjs/react/web/ui/prebuilt/Chain/provider.js.map +1 -0
  9. package/dist/cjs/react/web/ui/prebuilt/Token/icon.js.map +1 -1
  10. package/dist/cjs/version.js +1 -1
  11. package/dist/cjs/version.js.map +1 -1
  12. package/dist/esm/exports/react.js +4 -0
  13. package/dist/esm/exports/react.js.map +1 -1
  14. package/dist/esm/react/web/ui/prebuilt/Chain/icon.js +93 -0
  15. package/dist/esm/react/web/ui/prebuilt/Chain/icon.js.map +1 -0
  16. package/dist/esm/react/web/ui/prebuilt/Chain/name.js +121 -0
  17. package/dist/esm/react/web/ui/prebuilt/Chain/name.js.map +1 -0
  18. package/dist/esm/react/web/ui/prebuilt/Chain/provider.js +50 -0
  19. package/dist/esm/react/web/ui/prebuilt/Chain/provider.js.map +1 -0
  20. package/dist/esm/react/web/ui/prebuilt/Token/icon.js.map +1 -1
  21. package/dist/esm/version.js +1 -1
  22. package/dist/esm/version.js.map +1 -1
  23. package/dist/types/exports/react.d.ts +3 -0
  24. package/dist/types/exports/react.d.ts.map +1 -1
  25. package/dist/types/react/web/ui/prebuilt/Chain/icon.d.ts +106 -0
  26. package/dist/types/react/web/ui/prebuilt/Chain/icon.d.ts.map +1 -0
  27. package/dist/types/react/web/ui/prebuilt/Chain/name.d.ts +142 -0
  28. package/dist/types/react/web/ui/prebuilt/Chain/name.d.ts.map +1 -0
  29. package/dist/types/react/web/ui/prebuilt/Chain/provider.d.ts +48 -0
  30. package/dist/types/react/web/ui/prebuilt/Chain/provider.d.ts.map +1 -0
  31. package/dist/types/react/web/ui/prebuilt/Token/icon.d.ts +5 -0
  32. package/dist/types/react/web/ui/prebuilt/Token/icon.d.ts.map +1 -1
  33. package/dist/types/version.d.ts +1 -1
  34. package/dist/types/version.d.ts.map +1 -1
  35. package/package.json +1 -1
  36. package/src/exports/react.ts +14 -0
  37. package/src/react/web/ui/prebuilt/Chain/icon.tsx +154 -0
  38. package/src/react/web/ui/prebuilt/Chain/name.test.tsx +73 -0
  39. package/src/react/web/ui/prebuilt/Chain/name.tsx +185 -0
  40. package/src/react/web/ui/prebuilt/Chain/provider.test.tsx +34 -0
  41. package/src/react/web/ui/prebuilt/Chain/provider.tsx +73 -0
  42. package/src/react/web/ui/prebuilt/Token/icon.tsx +5 -0
  43. package/src/react/web/ui/prebuilt/Token/provider.test.tsx +44 -0
  44. package/src/react/web/ui/prebuilt/Token/symbol.test.tsx +30 -0
  45. package/src/version.ts +1 -1
@@ -0,0 +1,73 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { render, screen, waitFor } from "~test/react-render.js";
3
+ import { ethereum } from "../../../../../chains/chain-definitions/ethereum.js";
4
+ import { defineChain } from "../../../../../chains/utils.js";
5
+ import { ChainName } from "./name.js";
6
+ import { ChainProvider } from "./provider.js";
7
+
8
+ describe.runIf(process.env.TW_SECRET_KEY)("ChainName component", () => {
9
+ it("should return the correct chain name, if the name exists in the chain object", () => {
10
+ render(
11
+ <ChainProvider chain={ethereum}>
12
+ <ChainName />
13
+ </ChainProvider>,
14
+ );
15
+ waitFor(() =>
16
+ expect(
17
+ screen.getByText("Ethereum", {
18
+ exact: true,
19
+ selector: "span",
20
+ }),
21
+ ).toBeInTheDocument(),
22
+ );
23
+ });
24
+
25
+ it("should return the correct chain name, if the name is loaded from the server", () => {
26
+ render(
27
+ <ChainProvider chain={defineChain(1)}>
28
+ <ChainName />
29
+ </ChainProvider>,
30
+ );
31
+ waitFor(() =>
32
+ expect(
33
+ screen.getByText("Ethereum Mainnet", {
34
+ exact: true,
35
+ selector: "span",
36
+ }),
37
+ ).toBeInTheDocument(),
38
+ );
39
+ });
40
+
41
+ it("should return the correct FORMATTED chain name", () => {
42
+ render(
43
+ <ChainProvider chain={ethereum}>
44
+ <ChainName formatFn={(str: string) => `${str}-formatted`} />
45
+ </ChainProvider>,
46
+ );
47
+ waitFor(() =>
48
+ expect(
49
+ screen.getByText("Ethereum-formatted", {
50
+ exact: true,
51
+ selector: "span",
52
+ }),
53
+ ).toBeInTheDocument(),
54
+ );
55
+ });
56
+
57
+ it("should fallback properly when fail to resolve chain name", () => {
58
+ render(
59
+ <ChainProvider chain={defineChain(-1)}>
60
+ <ChainName fallbackComponent={<span>oops</span>} />
61
+ </ChainProvider>,
62
+ );
63
+
64
+ waitFor(() =>
65
+ expect(
66
+ screen.getByText("oops", {
67
+ exact: true,
68
+ selector: "span",
69
+ }),
70
+ ).toBeInTheDocument(),
71
+ );
72
+ });
73
+ });
@@ -0,0 +1,185 @@
1
+ "use client";
2
+
3
+ import { type UseQueryOptions, useQuery } from "@tanstack/react-query";
4
+ import type React from "react";
5
+ import type { JSX } from "react";
6
+ import { getChainMetadata } from "../../../../../chains/utils.js";
7
+ import { useChainContext } from "./provider.js";
8
+
9
+ /**
10
+ * Props for the ChainName component
11
+ * @component
12
+ * @chain
13
+ */
14
+ export interface ChainNameProps
15
+ extends Omit<React.HTMLAttributes<HTMLSpanElement>, "children"> {
16
+ /**
17
+ * This prop can be a string or a (async) function that resolves to a string, representing the name of the chain
18
+ * This is particularly useful if you already have a way to fetch the chain name.
19
+ */
20
+ nameResolver?: string | (() => string) | (() => Promise<string>);
21
+ /**
22
+ * A function to format the name's display value
23
+ * Particularly useful to avoid overflowing-UI issues
24
+ *
25
+ * ```tsx
26
+ * <ChainName formatFn={(str: string) => doSomething()} />
27
+ * ```
28
+ */
29
+ formatFn?: (str: string) => string;
30
+ /**
31
+ * This component will be shown while the name of the chain is being fetched
32
+ * If not passed, the component will return `null`.
33
+ *
34
+ * You can/should pass a loading sign or spinner to this prop.
35
+ * @example
36
+ * ```tsx
37
+ * <ChainName loadingComponent={<Spinner />} />
38
+ * ```
39
+ */
40
+ loadingComponent?: JSX.Element;
41
+ /**
42
+ * This component will be shown if the name fails to be retreived
43
+ * If not passed, the component will return `null`.
44
+ *
45
+ * You can/should pass a descriptive text/component to this prop, indicating that the
46
+ * name was not fetched succesfully
47
+ * @example
48
+ * ```tsx
49
+ * <ChainName fallbackComponent={"Failed to load"}
50
+ * />
51
+ * ```
52
+ */
53
+ fallbackComponent?: JSX.Element;
54
+ /**
55
+ * Optional `useQuery` params
56
+ */
57
+ queryOptions?: Omit<UseQueryOptions<string>, "queryFn" | "queryKey">;
58
+ }
59
+
60
+ /**
61
+ * This component fetches then shows the name of a chain.
62
+ * It inherits all the attributes of a HTML <span> component, hence you can style it just like how you would style a normal <span>
63
+ *
64
+ *
65
+ * @example
66
+ * ### Basic usage
67
+ * ```tsx
68
+ * import { ChainProvider, ChainName } from "thirdweb/react";
69
+ * import { ethereum } from "thirdweb/chains";
70
+ *
71
+ * <ChainProvider {...props}>
72
+ * <ChainName />
73
+ * </ChainProvider>
74
+ * ```
75
+ * Result:
76
+ * ```html
77
+ * <span>Ethereum Mainnet</span>
78
+ * ```
79
+ *
80
+ * ### Custom name resolver
81
+ * By default ChainName will call the thirdweb API to retrieve the chain name.
82
+ * However if you have a different way to fetch the name, you can pass the function to the `nameResolver` prop.
83
+ * Note: nameResolver should either be a string or a function (async) that returns a string.
84
+ * ```tsx
85
+ * async function fetchNameMethod() {
86
+ * // your own fetching logic
87
+ * return "the chain name";
88
+ * }
89
+ *
90
+ * <ChainName nameResolver={fetchNameMethod} />
91
+ * ```
92
+ *
93
+ * Alternatively you can also pass in a string directly:
94
+ * ```tsx
95
+ * <ChainName nameResolver="ETH Mainnet" />
96
+ * ```
97
+ *
98
+ *
99
+ * ### Format the name (capitalize, truncate, etc.)
100
+ * The ChainName component accepts a `formatFn` which takes in a string and outputs a string
101
+ * The function is used to modify the name of the chain
102
+ *
103
+ * ```tsx
104
+ * const concatStr = (str: string):string => str + "Network"
105
+ *
106
+ * <ChainProvider {...props}>
107
+ * <ChainName formatFn={concatStr} />
108
+ * </ChainProvider>
109
+ * ```
110
+ *
111
+ * Result:
112
+ * ```html
113
+ * <span>Ethereum Mainnet Network</span>
114
+ * ```
115
+ *
116
+ * ### Show a loading sign when the name is being fetched
117
+ * ```tsx
118
+ * import { ChainProvider, ChainName } from "thirdweb/react";
119
+ *
120
+ * <ChainProvider {...props}>
121
+ * <ChainName loadingComponent={<Spinner />} />
122
+ * </ChainProvider>
123
+ * ```
124
+ *
125
+ * ### Fallback to something when the name fails to resolve
126
+ * ```tsx
127
+ * <ChainProvider {...props}>
128
+ * <ChainName fallbackComponent={"Failed to load"} />
129
+ * </ChainProvider>
130
+ * ```
131
+ *
132
+ * ### Custom query options for useQuery
133
+ * This component uses `@tanstack-query`'s useQuery internally.
134
+ * You can use the `queryOptions` prop for more fine-grained control
135
+ * ```tsx
136
+ * <ChainName
137
+ * queryOptions={{
138
+ * enabled: isEnabled,
139
+ * retry: 4,
140
+ * }}
141
+ * />
142
+ * ```
143
+ *
144
+ * @component
145
+ * @chain
146
+ * @beta
147
+ */
148
+ export function ChainName({
149
+ nameResolver,
150
+ formatFn,
151
+ loadingComponent,
152
+ fallbackComponent,
153
+ queryOptions,
154
+ ...restProps
155
+ }: ChainNameProps) {
156
+ const { chain } = useChainContext();
157
+ const nameQuery = useQuery({
158
+ queryKey: ["_internal_chain_name_", chain.id] as const,
159
+ queryFn: async () => {
160
+ if (typeof nameResolver === "string") {
161
+ return nameResolver;
162
+ }
163
+ if (typeof nameResolver === "function") {
164
+ return nameResolver();
165
+ }
166
+ if (chain.name) {
167
+ return chain.name;
168
+ }
169
+ return getChainMetadata(chain).then((data) => data.name);
170
+ },
171
+ ...queryOptions,
172
+ });
173
+
174
+ if (nameQuery.isLoading) {
175
+ return loadingComponent || null;
176
+ }
177
+
178
+ if (!nameQuery.data) {
179
+ return fallbackComponent || null;
180
+ }
181
+
182
+ const displayValue = formatFn ? formatFn(nameQuery.data) : nameQuery.data;
183
+
184
+ return <span {...restProps}>{displayValue}</span>;
185
+ }
@@ -0,0 +1,34 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { render, screen, waitFor } from "~test/react-render.js";
3
+ import { ethereum } from "../../../../../chains/chain-definitions/ethereum.js";
4
+ import { ChainName } from "./name.js";
5
+ import { ChainProvider } from "./provider.js";
6
+
7
+ describe.runIf(process.env.TW_SECRET_KEY)("ChainProvider component", () => {
8
+ it("should render children correctly", () => {
9
+ render(
10
+ <ChainProvider chain={ethereum}>
11
+ <div>Child Component</div>
12
+ </ChainProvider>,
13
+ );
14
+
15
+ expect(screen.getByText("Child Component")).toBeInTheDocument();
16
+ });
17
+
18
+ it("should pass the chain correctly to the children props", () => {
19
+ render(
20
+ <ChainProvider chain={ethereum}>
21
+ <ChainName />
22
+ </ChainProvider>,
23
+ );
24
+
25
+ waitFor(() =>
26
+ expect(
27
+ screen.getByText("Ethereum", {
28
+ exact: true,
29
+ selector: "span",
30
+ }),
31
+ ).toBeInTheDocument(),
32
+ );
33
+ });
34
+ });
@@ -0,0 +1,73 @@
1
+ "use client";
2
+
3
+ import type React from "react";
4
+ import { createContext, useContext } from "react";
5
+ import type { Chain } from "../../../../../chains/types.js";
6
+
7
+ /**
8
+ * Props for the <ChainProvider /> component
9
+ * @component
10
+ * @chain
11
+ */
12
+ export type ChainProviderProps = {
13
+ chain: Chain;
14
+ };
15
+
16
+ const ChainProviderContext = /* @__PURE__ */ createContext<
17
+ ChainProviderProps | undefined
18
+ >(undefined);
19
+
20
+ /**
21
+ * A React context provider component that supplies Chain-related data to its child components.
22
+ *
23
+ * This component serves as a wrapper around the `ChainProviderContext.Provider` and passes
24
+ * the provided chain data down to all of its child components through the context API.
25
+ *
26
+ * @example
27
+ * ### Basic usage
28
+ * ```tsx
29
+ * import { ChainProvider, ChainIcon, ChainName } from "thirdweb/react";
30
+ * import { ethereum } from "thirdweb/chains";
31
+ *
32
+ * <ChainProvider chain={ethereum}>
33
+ * <ChainIcon />
34
+ * <ChainName />
35
+ * </ChainProvider>
36
+ * ```
37
+ *
38
+ * ### Usage with defineChain
39
+ * ```tsx
40
+ * import { defineChain } from "thirdweb/chains"l
41
+ * import { ChainProvider, ChainName } from "thirdweb/react";
42
+ *
43
+ * const chainId = someNumber;
44
+ *
45
+ * <ChainProvider chain={defineChain(chainId)}>
46
+ * <ChainName />
47
+ * </ChainProvider>
48
+ * ```
49
+ * @component
50
+ * @chain
51
+ */
52
+ export function ChainProvider(
53
+ props: React.PropsWithChildren<ChainProviderProps>,
54
+ ) {
55
+ return (
56
+ <ChainProviderContext.Provider value={props}>
57
+ {props.children}
58
+ </ChainProviderContext.Provider>
59
+ );
60
+ }
61
+
62
+ /**
63
+ * @internal
64
+ */
65
+ export function useChainContext() {
66
+ const ctx = useContext(ChainProviderContext);
67
+ if (!ctx) {
68
+ throw new Error(
69
+ "ChainProviderContext not found. Make sure you are using ChainName, ChainIcon, etc. inside a <ChainProvider /> component",
70
+ );
71
+ }
72
+ return ctx;
73
+ }
@@ -7,6 +7,11 @@ import { getContractMetadata } from "../../../../../extensions/common/read/getCo
7
7
  import { resolveScheme } from "../../../../../utils/ipfs.js";
8
8
  import { useTokenContext } from "./provider.js";
9
9
 
10
+ /**
11
+ * Props for the TokenIcon component
12
+ * @component
13
+ * @token
14
+ */
10
15
  export interface TokenIconProps
11
16
  extends Omit<React.ImgHTMLAttributes<HTMLImageElement>, "src"> {
12
17
  /**
@@ -0,0 +1,44 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { render, screen, waitFor } from "~test/react-render.js";
3
+ import { TEST_CLIENT } from "~test/test-clients.js";
4
+ import { ethereum } from "../../../../../chains/chain-definitions/ethereum.js";
5
+ import { NATIVE_TOKEN_ADDRESS } from "../../../../../constants/addresses.js";
6
+ import { TokenName } from "./name.js";
7
+ import { TokenProvider } from "./provider.js";
8
+
9
+ describe.runIf(process.env.TW_SECRET_KEY)("TokenProvider component", () => {
10
+ it("should render children correctly", () => {
11
+ render(
12
+ <TokenProvider
13
+ address={NATIVE_TOKEN_ADDRESS}
14
+ client={TEST_CLIENT}
15
+ chain={ethereum}
16
+ >
17
+ <div>Child Component</div>
18
+ </TokenProvider>,
19
+ );
20
+
21
+ expect(screen.getByText("Child Component")).toBeInTheDocument();
22
+ });
23
+
24
+ it("should pass the token data correctly to the children props", () => {
25
+ render(
26
+ <TokenProvider
27
+ address={NATIVE_TOKEN_ADDRESS}
28
+ client={TEST_CLIENT}
29
+ chain={ethereum}
30
+ >
31
+ <TokenName />
32
+ </TokenProvider>,
33
+ );
34
+
35
+ waitFor(() =>
36
+ expect(
37
+ screen.getByText("Ether", {
38
+ exact: true,
39
+ selector: "span",
40
+ }),
41
+ ).toBeInTheDocument(),
42
+ );
43
+ });
44
+ });
@@ -0,0 +1,30 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { render, screen, waitFor } from "~test/react-render.js";
3
+ import { TEST_CLIENT } from "~test/test-clients.js";
4
+ import { ethereum } from "../../../../../chains/chain-definitions/ethereum.js";
5
+ import { NATIVE_TOKEN_ADDRESS } from "../../../../../constants/addresses.js";
6
+ import { TokenProvider } from "./provider.js";
7
+ import { TokenSymbol } from "./symbol.js";
8
+
9
+ describe.runIf(process.env.TW_SECRET_KEY)("TokenSymbol component", () => {
10
+ it("should pass the address correctly to the children props", () => {
11
+ render(
12
+ <TokenProvider
13
+ address={NATIVE_TOKEN_ADDRESS}
14
+ client={TEST_CLIENT}
15
+ chain={ethereum}
16
+ >
17
+ <TokenSymbol />
18
+ </TokenProvider>,
19
+ );
20
+
21
+ waitFor(() =>
22
+ expect(
23
+ screen.getByText("ETH", {
24
+ exact: true,
25
+ selector: "span",
26
+ }),
27
+ ).toBeInTheDocument(),
28
+ );
29
+ });
30
+ });
package/src/version.ts CHANGED
@@ -1 +1 @@
1
- export const version = "5.71.0";
1
+ export const version = "5.72.0-nightly-a98550d229e7fd124e1977fcc64dbd1b602ce656-20241126000403";