Skip to content

Commit b7e1e42

Browse files
Fix showQrModal option not respected on desktop web
1 parent 3c8e444 commit b7e1e42

File tree

10 files changed

+503
-207
lines changed

10 files changed

+503
-207
lines changed

.changeset/social-dogs-bet.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"thirdweb": patch
3+
---
4+
5+
Fix showQrModal option not respected on desktop web

apps/playground-web/src/app/wallets/sign-in/headless/page.tsx

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ import { shortenAddress } from "thirdweb/utils";
7777
function App() {
7878
const account = useActiveAccount();
7979
const wallet = useActiveWallet();
80-
const { connect, isConnecting, error } = useConnect();
80+
const { connect, isConnecting, error, cancelConnection } = useConnect();
8181
const { disconnect } = useDisconnect();
8282
8383
if (account) {
@@ -99,7 +99,14 @@ function App() {
9999
connect(async () => {
100100
// 500+ wallets supported with id autocomplete
101101
const wallet = createWallet("io.metamask");
102-
await wallet.connect({ client });
102+
const isInstalled = !!injectedProvider("io.metamask");
103+
await wallet.connect({ client, ...(isInstalled ? {} : {
104+
walletConnect: {
105+
// if not installed, show qr modal
106+
showQrModal: true,
107+
onCancel: () => {
108+
cancelConnection();
109+
}) });
103110
return wallet;
104111
})
105112
}

apps/playground-web/src/components/sign-in/hooks.tsx

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import {
66
useDisconnect,
77
} from "thirdweb/react";
88
import { shortenAddress } from "thirdweb/utils";
9-
import { createWallet } from "thirdweb/wallets";
9+
import { createWallet, injectedProvider } from "thirdweb/wallets";
1010
import { THIRDWEB_CLIENT } from "../../lib/client";
1111
import { Button } from "../ui/button";
1212

@@ -21,6 +21,17 @@ export function HooksPreview() {
2121
const adminWallet = createWallet("io.metamask");
2222
await adminWallet.connect({
2323
client: THIRDWEB_CLIENT,
24+
...(injectedProvider("io.metamask")
25+
? {}
26+
: {
27+
walletConnect: {
28+
showQrModal: true,
29+
onCancel: () => {
30+
console.log("onCancel");
31+
connectMutation.cancelConnection();
32+
},
33+
},
34+
}),
2435
});
2536
return adminWallet;
2637
});

apps/playground-web/src/components/sign-in/modal.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,6 @@ export function ModalPreview({ enableAuth }: { enableAuth?: boolean }) {
5454
auth: enableAuth ? playgroundAuth : undefined,
5555
client: THIRDWEB_CLIENT,
5656
});
57-
console.log("connected", wallet);
5857
return wallet;
5958
};
6059

packages/thirdweb/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
"ora": "8.2.0",
3737
"ox": "0.7.0",
3838
"prompts": "2.4.2",
39+
"qrcode": "1.5.3",
3940
"toml": "3.0.0",
4041
"uqr": "0.1.2",
4142
"viem": "2.28.1",

packages/thirdweb/src/react/core/hooks/wallets/useConnect.ts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,5 +79,15 @@ export function useConnect(options?: ConnectManagerOptions) {
7979
[connect, options, setConnectionStatus],
8080
);
8181

82-
return { connect: handleConnection, error, isConnecting } as const;
82+
const cancelConnection = useCallback(() => {
83+
setIsConnecting(false);
84+
setConnectionStatus("disconnected");
85+
}, [setConnectionStatus]);
86+
87+
return {
88+
connect: handleConnection,
89+
error,
90+
isConnecting,
91+
cancelConnection,
92+
} as const;
8393
}

packages/thirdweb/src/wallets/create-wallet.ts

Lines changed: 85 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import { inAppWallet } from "./in-app/web/in-app.js";
1717
import { getInjectedProvider } from "./injected/index.js";
1818
import type { Account, Wallet } from "./interfaces/wallet.js";
1919
import { smartWallet } from "./smart/smart-wallet.js";
20+
import type { QROverlay } from "./wallet-connect/qr-overlay.js";
2021
import type { WCConnectOptions } from "./wallet-connect/types.js";
2122
import { createWalletEmitter } from "./wallet-emitter.js";
2223
import type {
@@ -299,30 +300,90 @@ export function createWallet<const ID extends WalletId>(
299300
"./wallet-connect/controller.js"
300301
);
301302

302-
const [
303-
connectedAccount,
304-
connectedChain,
305-
doDisconnect,
306-
doSwitchChain,
307-
] = await connectWC(
308-
wcOptions,
309-
emitter,
310-
wallet.id as WCSupportedWalletIds | "walletConnect",
311-
webLocalStorage,
312-
sessionHandler,
313-
);
314-
// set the states
315-
account = connectedAccount;
316-
chain = connectedChain;
317-
handleDisconnect = doDisconnect;
318-
handleSwitchChain = doSwitchChain;
319-
trackConnect({
320-
chainId: chain.id,
321-
client: wcOptions.client,
322-
walletAddress: account.address,
323-
walletType: id,
324-
});
325-
return account;
303+
let qrOverlay: QROverlay | undefined;
304+
305+
try {
306+
const [
307+
connectedAccount,
308+
connectedChain,
309+
doDisconnect,
310+
doSwitchChain,
311+
] = await connectWC(
312+
{
313+
...wcOptions,
314+
walletConnect: {
315+
...wcOptions.walletConnect,
316+
onDisplayUri: wcOptions.walletConnect?.showQrModal
317+
? async (uri) => {
318+
// Check if we're in a browser environment
319+
if (
320+
typeof window !== "undefined" &&
321+
typeof document !== "undefined"
322+
) {
323+
try {
324+
const { createQROverlay } = await import(
325+
"./wallet-connect/qr-overlay.js"
326+
);
327+
328+
// Clean up any existing overlay
329+
if (qrOverlay) {
330+
qrOverlay.destroy();
331+
}
332+
333+
// Create new QR overlay
334+
qrOverlay = createQROverlay(uri, {
335+
theme:
336+
wcOptions.walletConnect?.qrModalOptions
337+
?.themeMode ?? "dark",
338+
qrSize: 280,
339+
showCloseButton: true,
340+
onCancel: () => {
341+
wcOptions.walletConnect?.onCancel?.();
342+
},
343+
});
344+
} catch (error) {
345+
console.error(
346+
"Failed to create QR overlay:",
347+
error,
348+
);
349+
}
350+
}
351+
}
352+
: undefined,
353+
},
354+
},
355+
emitter,
356+
wallet.id as WCSupportedWalletIds | "walletConnect",
357+
webLocalStorage,
358+
sessionHandler,
359+
);
360+
361+
// Clean up QR overlay on successful connection
362+
if (qrOverlay) {
363+
qrOverlay.destroy();
364+
qrOverlay = undefined;
365+
}
366+
367+
// set the states
368+
account = connectedAccount;
369+
chain = connectedChain;
370+
handleDisconnect = doDisconnect;
371+
handleSwitchChain = doSwitchChain;
372+
trackConnect({
373+
chainId: chain.id,
374+
client: wcOptions.client,
375+
walletAddress: account.address,
376+
walletType: id,
377+
});
378+
return account;
379+
} catch (error) {
380+
// Clean up QR overlay on connection error
381+
if (qrOverlay) {
382+
qrOverlay.destroy();
383+
qrOverlay = undefined;
384+
}
385+
throw error;
386+
}
326387
}
327388

328389
if (id === "walletConnect") {

0 commit comments

Comments
 (0)