thirdweb 5.32.1 → 5.32.2-nightly-a6ed6e66dae7f2fa239c76a57e93b545e5d8da8d-20240704000330

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 (66) hide show
  1. package/dist/cjs/adapters/ethers5.js +2 -2
  2. package/dist/cjs/adapters/ethers5.js.map +1 -1
  3. package/dist/cjs/contract/verification/index.js +52 -28
  4. package/dist/cjs/contract/verification/index.js.map +1 -1
  5. package/dist/cjs/react/core/hooks/wallets/useConnect.js +2 -2
  6. package/dist/cjs/react/core/hooks/wallets/useConnect.js.map +1 -1
  7. package/dist/cjs/react/native/ui/components/WalletImage.js +18 -20
  8. package/dist/cjs/react/native/ui/components/WalletImage.js.map +1 -1
  9. package/dist/cjs/react/native/ui/connect/ConnectButton.js +1 -6
  10. package/dist/cjs/react/native/ui/connect/ConnectButton.js.map +1 -1
  11. package/dist/cjs/react/native/ui/connect/ConnectModal.js +64 -15
  12. package/dist/cjs/react/native/ui/connect/ConnectModal.js.map +1 -1
  13. package/dist/cjs/react/native/ui/connect/ExternalWalletsList.js +12 -18
  14. package/dist/cjs/react/native/ui/connect/ExternalWalletsList.js.map +1 -1
  15. package/dist/cjs/react/native/ui/connect/InAppWalletUI.js +39 -34
  16. package/dist/cjs/react/native/ui/connect/InAppWalletUI.js.map +1 -1
  17. package/dist/cjs/react/native/ui/connect/WalletLoadingThumbnail.js +51 -0
  18. package/dist/cjs/react/native/ui/connect/WalletLoadingThumbnail.js.map +1 -0
  19. package/dist/cjs/version.js +1 -1
  20. package/dist/cjs/version.js.map +1 -1
  21. package/dist/esm/adapters/ethers5.js +2 -2
  22. package/dist/esm/adapters/ethers5.js.map +1 -1
  23. package/dist/esm/contract/verification/index.js +52 -28
  24. package/dist/esm/contract/verification/index.js.map +1 -1
  25. package/dist/esm/react/core/hooks/wallets/useConnect.js +2 -2
  26. package/dist/esm/react/core/hooks/wallets/useConnect.js.map +1 -1
  27. package/dist/esm/react/native/ui/components/WalletImage.js +17 -20
  28. package/dist/esm/react/native/ui/components/WalletImage.js.map +1 -1
  29. package/dist/esm/react/native/ui/connect/ConnectButton.js +1 -6
  30. package/dist/esm/react/native/ui/connect/ConnectButton.js.map +1 -1
  31. package/dist/esm/react/native/ui/connect/ConnectModal.js +65 -16
  32. package/dist/esm/react/native/ui/connect/ConnectModal.js.map +1 -1
  33. package/dist/esm/react/native/ui/connect/ExternalWalletsList.js +12 -18
  34. package/dist/esm/react/native/ui/connect/ExternalWalletsList.js.map +1 -1
  35. package/dist/esm/react/native/ui/connect/InAppWalletUI.js +39 -34
  36. package/dist/esm/react/native/ui/connect/InAppWalletUI.js.map +1 -1
  37. package/dist/esm/react/native/ui/connect/WalletLoadingThumbnail.js +49 -0
  38. package/dist/esm/react/native/ui/connect/WalletLoadingThumbnail.js.map +1 -0
  39. package/dist/esm/version.js +1 -1
  40. package/dist/esm/version.js.map +1 -1
  41. package/dist/types/contract/verification/index.d.ts +1 -0
  42. package/dist/types/contract/verification/index.d.ts.map +1 -1
  43. package/dist/types/react/native/ui/components/WalletImage.d.ts +1 -0
  44. package/dist/types/react/native/ui/components/WalletImage.d.ts.map +1 -1
  45. package/dist/types/react/native/ui/connect/ConnectButton.d.ts.map +1 -1
  46. package/dist/types/react/native/ui/connect/ConnectModal.d.ts +8 -0
  47. package/dist/types/react/native/ui/connect/ConnectModal.d.ts.map +1 -1
  48. package/dist/types/react/native/ui/connect/ExternalWalletsList.d.ts +4 -2
  49. package/dist/types/react/native/ui/connect/ExternalWalletsList.d.ts.map +1 -1
  50. package/dist/types/react/native/ui/connect/InAppWalletUI.d.ts +6 -2
  51. package/dist/types/react/native/ui/connect/InAppWalletUI.d.ts.map +1 -1
  52. package/dist/types/react/native/ui/connect/WalletLoadingThumbnail.d.ts +10 -0
  53. package/dist/types/react/native/ui/connect/WalletLoadingThumbnail.d.ts.map +1 -0
  54. package/dist/types/version.d.ts +1 -1
  55. package/dist/types/version.d.ts.map +1 -1
  56. package/package.json +1 -1
  57. package/src/adapters/ethers5.ts +2 -2
  58. package/src/contract/verification/index.ts +63 -30
  59. package/src/react/core/hooks/wallets/useConnect.ts +2 -2
  60. package/src/react/native/ui/components/WalletImage.tsx +18 -20
  61. package/src/react/native/ui/connect/ConnectButton.tsx +0 -11
  62. package/src/react/native/ui/connect/ConnectModal.tsx +158 -13
  63. package/src/react/native/ui/connect/ExternalWalletsList.tsx +18 -35
  64. package/src/react/native/ui/connect/InAppWalletUI.tsx +49 -67
  65. package/src/react/native/ui/connect/WalletLoadingThumbnail.tsx +98 -0
  66. package/src/version.ts +1 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"WalletLoadingThumbnail.d.ts","sourceRoot":"","sources":["../../../../../../src/react/native/ui/connect/WalletLoadingThumbnail.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,sCAAsC,CAAC;AAQlE,UAAU,KAAK;IACb,KAAK,EAAE,KAAK,CAAC;IACb,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,iBAAS,sBAAsB,CAAC,EAC9B,KAAK,EACL,QAAQ,EACR,SAAS,EACT,SAAS,GACV,EAAE,KAAK,8CA8DP;AAYD,eAAe,sBAAsB,CAAC"}
@@ -1,2 +1,2 @@
1
- export declare const version = "5.32.1";
1
+ export declare const version = "5.32.2-nightly-a6ed6e66dae7f2fa239c76a57e93b545e5d8da8d-20240704000330";
2
2
  //# sourceMappingURL=version.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"version.d.ts","sourceRoot":"","sources":["../../src/version.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,OAAO,WAAW,CAAC"}
1
+ {"version":3,"file":"version.d.ts","sourceRoot":"","sources":["../../src/version.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,OAAO,2EAA2E,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "thirdweb",
3
- "version": "5.32.1",
3
+ "version": "5.32.2-nightly-a6ed6e66dae7f2fa239c76a57e93b545e5d8da8d-20240704000330",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/thirdweb-dev/js.git#main"
@@ -339,7 +339,7 @@ export async function toEthersSigner(
339
339
  if (!account.sendTransaction) {
340
340
  throw new Error("Account does not support sendTransaction");
341
341
  }
342
- const awaitedTx = await ethers.utils.resolveProperties(transaction);
342
+ const awaitedTx = await this.populateTransaction(transaction);
343
343
  const alignedTx = await alignTxFromEthers(awaitedTx, ethers);
344
344
  const tx = prepareTransaction({
345
345
  client: client,
@@ -364,7 +364,7 @@ export async function toEthersSigner(
364
364
  chainId: tx.chain.id,
365
365
  from: account.address,
366
366
  data: alignedTx.data ?? "0x",
367
- nonce: alignedTx.nonce ?? -1,
367
+ nonce: alignedTx.nonce ?? 0,
368
368
  value: ethers.BigNumber.from(alignedTx.value ?? 0),
369
369
  gasLimit: ethers.BigNumber.from(alignedTx.gas ?? 0),
370
370
  // biome-ignore lint/style/noNonNullAssertion: TODO: fix later
@@ -16,6 +16,7 @@ type VerifyContractOptions = {
16
16
  explorerApiUrl: string;
17
17
  explorerApiKey: string;
18
18
  encodedConstructorArgs?: string;
19
+ type?: "etherscan" | "blockscoutV1" | "blockscoutV2" | "routescan";
19
20
  };
20
21
 
21
22
  /**
@@ -105,39 +106,71 @@ export async function verifyContract(
105
106
  const targets = Object.keys(compilationTarget);
106
107
  const contractPath = targets[0];
107
108
 
108
- const encodedArgs = options.encodedConstructorArgs
109
- ? options.encodedConstructorArgs
110
- : await fetchConstructorParams({
111
- abi: compilerMetadata?.metadata?.output?.abi || [],
112
- contract: options.contract,
113
- explorerApiUrl: options.explorerApiUrl,
114
- explorerApiKey: options.explorerApiKey,
115
- });
116
-
117
- const requestBody: Record<string, string> = {
118
- apikey: options.explorerApiKey,
119
- module: "contract",
120
- action: "verifysourcecode",
121
- contractaddress: options.contract.address,
122
- sourceCode: JSON.stringify(compilerInput),
123
- codeformat: "solidity-standard-json-input",
124
- contractname: `${contractPath}:${compilerMetadata.name}`,
125
- compilerversion: `v${compilerMetadata.metadata.compiler.version}`,
126
- constructorArguements: encodedArgs,
127
- };
109
+ if (options.type === "blockscoutV2") {
110
+ const metadataBlob = new Blob([JSON.stringify(compilerInput)], {
111
+ type: "application/json",
112
+ });
113
+ const formData = new FormData();
114
+ formData.append("address_hash", options.contract.address);
115
+ formData.append(
116
+ "contract_name",
117
+ `${contractPath}:${compilerMetadata.name}`,
118
+ );
119
+ formData.append(
120
+ "compiler_version",
121
+ `v${compilerMetadata.metadata.compiler.version}`,
122
+ );
123
+ formData.append("autodetect_constructor_args", "true");
124
+ formData.append("files[0]", metadataBlob, "metadata.json");
125
+
126
+ const result = await fetch(
127
+ `${options.explorerApiUrl}/v2/smart-contracts/${options.contract.address.toLowerCase()}/verification/via/standard-input`,
128
+ {
129
+ method: "POST",
130
+ body: formData,
131
+ },
132
+ );
133
+ const data = await result.json();
128
134
 
129
- const parameters = new URLSearchParams({ ...requestBody });
130
- const result = await fetch(options.explorerApiUrl, {
131
- method: "POST",
132
- headers: { "Content-Type": "application/x-www-form-urlencoded" },
133
- body: parameters.toString(),
134
- });
135
+ if (data.message) {
136
+ return data.message;
137
+ } else {
138
+ throw new Error(`${data}`);
139
+ }
140
+ } else {
141
+ const encodedArgs = options.encodedConstructorArgs
142
+ ? options.encodedConstructorArgs
143
+ : await fetchConstructorParams({
144
+ abi: compilerMetadata?.metadata?.output?.abi || [],
145
+ contract: options.contract,
146
+ explorerApiUrl: options.explorerApiUrl,
147
+ explorerApiKey: options.explorerApiKey,
148
+ });
135
149
 
136
- const data = await result.json();
137
- if (data.status === RequestStatus.OK) {
138
- return data.result;
150
+ const requestBody: Record<string, string> = {
151
+ apikey: options.explorerApiKey,
152
+ module: "contract",
153
+ action: "verifysourcecode",
154
+ contractaddress: options.contract.address,
155
+ sourceCode: JSON.stringify(compilerInput),
156
+ codeformat: "solidity-standard-json-input",
157
+ contractname: `${contractPath}:${compilerMetadata.name}`,
158
+ compilerversion: `v${compilerMetadata.metadata.compiler.version}`,
159
+ constructorArguements: encodedArgs,
160
+ };
161
+
162
+ const parameters = new URLSearchParams({ ...requestBody });
163
+ const result = await fetch(options.explorerApiUrl, {
164
+ method: "POST",
165
+ headers: { "Content-Type": "application/x-www-form-urlencoded" },
166
+ body: parameters.toString(),
167
+ });
168
+ const data = await result.json();
169
+ if (data.status === RequestStatus.OK) {
170
+ return data.result;
171
+ }
172
+ throw new Error(`${data.result}`);
139
173
  }
140
- throw new Error(`${data.result}`);
141
174
  }
142
175
 
143
176
  const VerificationStatus = {
@@ -18,13 +18,13 @@ export function useConnectCore(
18
18
  // reset error state
19
19
  setError(null);
20
20
  if (typeof walletOrFn !== "function") {
21
- return connect(walletOrFn, options);
21
+ return await connect(walletOrFn, options);
22
22
  }
23
23
 
24
24
  setIsConnecting(true);
25
25
  try {
26
26
  const w = await walletOrFn();
27
- return connect(w, options);
27
+ return await connect(w, options);
28
28
  } catch (e) {
29
29
  console.error(e);
30
30
  setError(e as Error);
@@ -42,26 +42,7 @@ export const WalletImage = (props: {
42
42
  (wallet.id === "inApp" || wallet.id === "smart")
43
43
  ) {
44
44
  const lastAuthProvider = await getLastAuthProvider(nativeLocalStorage);
45
- switch (lastAuthProvider) {
46
- case "phone":
47
- imageData = PHONE_ICON;
48
- break;
49
- case "email":
50
- imageData = EMAIL_ICON;
51
- break;
52
- case "google":
53
- imageData = GOOGLE_ICON;
54
- break;
55
- case "apple":
56
- imageData = APPLE_ICON;
57
- break;
58
- case "facebook":
59
- imageData = FACEBOOK_ICON;
60
- break;
61
- default:
62
- imageData = WALLET_ICON;
63
- break;
64
- }
45
+ imageData = getAuthProviderImage(lastAuthProvider);
65
46
  return imageData;
66
47
  }
67
48
  try {
@@ -79,3 +60,20 @@ export const WalletImage = (props: {
79
60
  const data = ensAvatar || imageData || WALLET_ICON;
80
61
  return <RNImage theme={props.theme} data={data} size={size} />;
81
62
  };
63
+
64
+ export function getAuthProviderImage(lastAuthProvider: string | null): string {
65
+ switch (lastAuthProvider) {
66
+ case "phone":
67
+ return PHONE_ICON;
68
+ case "email":
69
+ return EMAIL_ICON;
70
+ case "google":
71
+ return GOOGLE_ICON;
72
+ case "apple":
73
+ return APPLE_ICON;
74
+ case "facebook":
75
+ return FACEBOOK_ICON;
76
+ default:
77
+ return WALLET_ICON;
78
+ }
79
+ }
@@ -138,17 +138,6 @@ export function ConnectButton(props: ConnectButtonProps) {
138
138
  wallet={wallet}
139
139
  account={account}
140
140
  />
141
- ) : status === "connecting" ? (
142
- <View
143
- style={{
144
- flexDirection: "column",
145
- flex: 1,
146
- alignItems: "center",
147
- justifyContent: "center",
148
- }}
149
- >
150
- <ThemedSpinner color={theme.colors.primaryText} size={32} />
151
- </View>
152
141
  ) : (
153
142
  <ConnectModal
154
143
  {...props}
@@ -1,28 +1,39 @@
1
- import { useState } from "react";
1
+ import { useCallback, useState } from "react";
2
2
  import { Platform, StyleSheet, View } from "react-native";
3
3
  import { SvgXml } from "react-native-svg";
4
4
  import type { MultiStepAuthProviderType } from "../../../../wallets/in-app/core/authentication/type.js";
5
+ import type { InAppWalletAuth } from "../../../../wallets/in-app/core/wallet/types.js";
5
6
  import type { Wallet } from "../../../../wallets/interfaces/wallet.js";
6
7
  import { parseTheme } from "../../../core/design-system/CustomThemeProvider.js";
7
8
  import type { Theme } from "../../../core/design-system/index.js";
8
9
  import type { ConnectButtonProps } from "../../../core/hooks/connection/ConnectButtonProps.js";
9
10
  import type { ConnectEmbedProps } from "../../../core/hooks/connection/ConnectEmbedProps.js";
10
11
  import { genericWalletIcon } from "../../../core/utils/socialIcons.js";
12
+ import { useWalletInfo } from "../../../core/utils/wallet.js";
11
13
  import { radius, spacing } from "../../design-system/index.js";
12
14
  import { useActiveWallet } from "../../hooks/wallets/useActiveWallet.js";
13
- import { useConnect } from "../../hooks/wallets/useConnect.js";
15
+ import { connectionManager } from "../../index.js";
14
16
  import { getDefaultWallets } from "../../wallets/defaultWallets.js";
15
17
  import { type ContainerType, Header } from "../components/Header.js";
18
+ import { RNImage } from "../components/RNImage.js";
19
+ import {
20
+ WalletImage,
21
+ getAuthProviderImage,
22
+ } from "../components/WalletImage.js";
16
23
  import { ThemedButtonWithIcon } from "../components/button.js";
17
24
  import { Spacer } from "../components/spacer.js";
18
25
  import { ThemedText } from "../components/text.js";
19
26
  import { ThemedView } from "../components/view.js";
20
27
  import { TW_ICON } from "../icons/svgs.js";
28
+ import { ErrorView } from "./ErrorView.js";
21
29
  import { ExternalWalletsList } from "./ExternalWalletsList.js";
22
30
  import { InAppWalletUI, OtpLogin } from "./InAppWalletUI.js";
31
+ import WalletLoadingThumbnail from "./WalletLoadingThumbnail.js";
23
32
 
24
33
  export type ModalState =
25
34
  | { screen: "base" }
35
+ | { screen: "connecting"; wallet: Wallet; authMethod?: InAppWalletAuth }
36
+ | { screen: "error"; error: string }
26
37
  | { screen: "otp"; auth: MultiStepAuthProviderType; wallet: Wallet<"inApp"> }
27
38
  | { screen: "external_wallets" };
28
39
 
@@ -63,17 +74,44 @@ export function ConnectModal(
63
74
  containerType: ContainerType;
64
75
  },
65
76
  ) {
66
- const { theme, client, containerType, accountAbstraction, onConnect } = props;
67
- const connectMutation = useConnect({
77
+ const {
78
+ theme,
68
79
  client,
80
+ containerType,
69
81
  accountAbstraction,
70
- onConnect: (wallet) => {
71
- props.onClose?.();
72
- onConnect?.(wallet);
82
+ onConnect,
83
+ onClose,
84
+ } = props;
85
+ const [modalState, setModalState] = useState<ModalState>({ screen: "base" });
86
+ const connector = useCallback(
87
+ async (args: {
88
+ wallet: Wallet;
89
+ connectFn: () => Promise<Wallet>;
90
+ authMethod?: InAppWalletAuth;
91
+ }) => {
92
+ setModalState({
93
+ screen: "connecting",
94
+ wallet: args.wallet,
95
+ authMethod: args.authMethod,
96
+ });
97
+ try {
98
+ const w = await args.connectFn();
99
+ await connectionManager.connect(w, {
100
+ client,
101
+ accountAbstraction,
102
+ onConnect,
103
+ });
104
+ onClose?.();
105
+ } catch (error) {
106
+ setModalState({
107
+ screen: "error",
108
+ error: (error as Error)?.message || "unknown error",
109
+ });
110
+ }
73
111
  },
74
- });
112
+ [client, accountAbstraction, onConnect, onClose],
113
+ );
75
114
  const wallets = props.wallets || getDefaultWallets(props);
76
- const [modalState, setModalState] = useState<ModalState>({ screen: "base" });
77
115
  const inAppWallet = wallets.find((wallet) => wallet.id === "inApp") as
78
116
  | Wallet<"inApp">
79
117
  | undefined;
@@ -105,7 +143,7 @@ export function ConnectModal(
105
143
  client={client}
106
144
  setScreen={setModalState}
107
145
  theme={theme}
108
- connectMutation={connectMutation}
146
+ connector={connector}
109
147
  />
110
148
  </View>
111
149
  {containerType === "modal" ? (
@@ -131,9 +169,61 @@ export function ConnectModal(
131
169
  theme={theme}
132
170
  externalWallets={externalWallets}
133
171
  client={client}
134
- connectMutation={connectMutation}
172
+ connector={connector}
173
+ containerType={containerType}
174
+ />
175
+ </>
176
+ );
177
+ break;
178
+ }
179
+ case "connecting": {
180
+ content = (
181
+ <>
182
+ <Header
183
+ theme={theme}
184
+ onClose={props.onClose}
135
185
  containerType={containerType}
186
+ onBack={() => setModalState({ screen: "base" })}
187
+ />
188
+ {containerType === "modal" ? (
189
+ <View style={{ flex: 1 }} />
190
+ ) : (
191
+ <Spacer size="lg" />
192
+ )}
193
+ <LoadingView
194
+ theme={theme}
195
+ wallet={modalState.wallet}
196
+ authProvider={modalState.authMethod}
136
197
  />
198
+ {containerType === "modal" ? (
199
+ <View style={{ flex: 1 }} />
200
+ ) : (
201
+ <Spacer size="md" />
202
+ )}
203
+ </>
204
+ );
205
+ break;
206
+ }
207
+ case "error": {
208
+ content = (
209
+ <>
210
+ <Header
211
+ theme={theme}
212
+ onClose={props.onClose}
213
+ containerType={containerType}
214
+ onBack={() => setModalState({ screen: "base" })}
215
+ />
216
+ {containerType === "modal" ? (
217
+ <View style={{ flex: 1 }} />
218
+ ) : (
219
+ <Spacer size="lg" />
220
+ )}
221
+ <ErrorView theme={theme} title={modalState.error} />
222
+ {containerType === "modal" ? (
223
+ <View style={{ flex: 1 }} />
224
+ ) : (
225
+ <Spacer size="md" />
226
+ )}
137
227
  </>
138
228
  );
139
229
  break;
@@ -165,7 +255,7 @@ export function ConnectModal(
165
255
  setScreen={setModalState}
166
256
  client={client}
167
257
  theme={theme}
168
- connectMutation={connectMutation}
258
+ connector={connector}
169
259
  />
170
260
  {externalWallets.length > 0 ? (
171
261
  <>
@@ -199,7 +289,7 @@ export function ConnectModal(
199
289
  theme={theme}
200
290
  externalWallets={externalWallets}
201
291
  client={client}
202
- connectMutation={connectMutation}
292
+ connector={connector}
203
293
  containerType={containerType}
204
294
  />
205
295
  </View>
@@ -225,6 +315,56 @@ export function ConnectModal(
225
315
  );
226
316
  }
227
317
 
318
+ function LoadingView({
319
+ theme,
320
+ wallet,
321
+ authProvider,
322
+ }: { theme: Theme; wallet: Wallet; authProvider?: InAppWalletAuth }) {
323
+ const walletInfo = useWalletInfo(wallet.id);
324
+ return (
325
+ <View
326
+ style={{
327
+ flexDirection: "column",
328
+ flex: 1,
329
+ alignItems: "center",
330
+ justifyContent: "center",
331
+ paddingVertical: spacing.xl,
332
+ }}
333
+ >
334
+ <WalletLoadingThumbnail theme={theme} imageSize={100}>
335
+ {authProvider ? (
336
+ <View
337
+ style={{
338
+ borderRadius: spacing.md,
339
+ padding: spacing.xs,
340
+ }}
341
+ >
342
+ <RNImage
343
+ theme={theme}
344
+ size={90}
345
+ data={getAuthProviderImage(authProvider)}
346
+ />
347
+ </View>
348
+ ) : (
349
+ <WalletImage theme={theme} size={90} wallet={wallet} />
350
+ )}
351
+ </WalletLoadingThumbnail>
352
+ <Spacer size="xl" />
353
+ <ThemedText theme={theme} type="subtitle">
354
+ {authProvider
355
+ ? `Connecting with ${capitalizeFirstLetter(authProvider)}`
356
+ : "Awaiting confirmation"}
357
+ </ThemedText>
358
+ <Spacer size="sm" />
359
+ <ThemedText theme={theme} type="subtext">
360
+ {authProvider
361
+ ? `Sign into your ${capitalizeFirstLetter(authProvider)} account`
362
+ : `Accept the connection request in ${walletInfo.data?.name}`}
363
+ </ThemedText>
364
+ </View>
365
+ );
366
+ }
367
+
228
368
  function OrDivider({ theme }: { theme: Theme }) {
229
369
  return (
230
370
  <View
@@ -284,6 +424,11 @@ function PoweredByThirdweb({ theme }: { theme: Theme }) {
284
424
  );
285
425
  }
286
426
 
427
+ function capitalizeFirstLetter(str: string): string {
428
+ if (!str) return str;
429
+ return str.charAt(0).toUpperCase() + str.slice(1);
430
+ }
431
+
287
432
  const styles = StyleSheet.create({
288
433
  modalContainer: {
289
434
  flex: 1,
@@ -1,4 +1,3 @@
1
- import { useState } from "react";
2
1
  import {
3
2
  Image,
4
3
  Linking,
@@ -12,32 +11,33 @@ import type { Wallet } from "../../../../wallets/interfaces/wallet.js";
12
11
  import type { Theme } from "../../../core/design-system/index.js";
13
12
  import { useWalletImage, useWalletInfo } from "../../../core/utils/wallet.js";
14
13
  import { spacing } from "../../design-system/index.js";
15
- import type { useConnect } from "../../hooks/wallets/useConnect.js";
16
14
  import type { ContainerType } from "../components/Header.js";
17
15
  import { Skeleton } from "../components/Skeleton.js";
18
- import { ThemedSpinner } from "../components/spinner.js";
19
16
  import { ThemedText } from "../components/text.js";
20
17
 
21
18
  export type ExternalWalletsUiProps = {
22
19
  theme: Theme;
23
20
  client: ThirdwebClient;
24
- connectMutation: ReturnType<typeof useConnect>;
21
+ connector: (args: {
22
+ wallet: Wallet;
23
+ connectFn: () => Promise<Wallet>;
24
+ }) => Promise<void>;
25
25
  containerType: ContainerType;
26
26
  };
27
27
 
28
28
  export function ExternalWalletsList(
29
29
  props: ExternalWalletsUiProps & { externalWallets: Wallet[] },
30
30
  ) {
31
- const { connectMutation, client, theme } = props;
32
- const [selectedWallet, setSelectedWallet] = useState<Wallet>();
33
-
31
+ const { connector, client, theme } = props;
34
32
  const connectWallet = (wallet: Wallet) => {
35
- setSelectedWallet(wallet);
36
- connectMutation.connect(async () => {
37
- await wallet.connect({
38
- client,
39
- });
40
- return wallet;
33
+ connector({
34
+ wallet,
35
+ connectFn: async () => {
36
+ await wallet.connect({
37
+ client,
38
+ });
39
+ return wallet;
40
+ },
41
41
  });
42
42
  };
43
43
 
@@ -57,9 +57,6 @@ export function ExternalWalletsList(
57
57
  wallet={wallet}
58
58
  connectWallet={connectWallet}
59
59
  theme={theme}
60
- isConnecting={
61
- connectMutation.isConnecting && wallet.id === selectedWallet?.id
62
- }
63
60
  />
64
61
  ))}
65
62
  </View>
@@ -72,32 +69,18 @@ export function ExternalWalletsList(
72
69
  function ExternalWalletRow(props: {
73
70
  theme: Theme;
74
71
  wallet: Wallet;
75
- isConnecting: boolean;
76
72
  connectWallet: (wallet: Wallet) => void;
77
73
  }) {
78
- const { wallet, theme, isConnecting, connectWallet } = props;
74
+ const { wallet, theme, connectWallet } = props;
79
75
  const imageQuery = useWalletImage(wallet.id);
80
76
  const infoQuery = useWalletInfo(wallet.id);
81
77
  return (
82
78
  <TouchableOpacity style={styles.row} onPress={() => connectWallet(wallet)}>
83
79
  {imageQuery.data ? (
84
- isConnecting ? (
85
- <View
86
- style={{
87
- width: 52,
88
- height: 52,
89
- justifyContent: "center",
90
- alignItems: "center",
91
- }}
92
- >
93
- <ThemedSpinner color={theme.colors.primaryText} />
94
- </View>
95
- ) : (
96
- <Image
97
- source={{ uri: imageQuery.data ?? "" }}
98
- style={{ width: 52, height: 52, borderRadius: 6 }}
99
- />
100
- )
80
+ <Image
81
+ source={{ uri: imageQuery.data ?? "" }}
82
+ style={{ width: 52, height: 52, borderRadius: 6 }}
83
+ />
101
84
  ) : (
102
85
  <Skeleton
103
86
  theme={theme}