Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .changeset/bright-radios-shake.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@thirdweb-dev/wallets": patch
"@thirdweb-dev/react": patch
---

add SignerWallet
6 changes: 5 additions & 1 deletion packages/react-core/src/core/providers/thirdweb-provider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,15 @@ import {
createAsyncLocalStorage,
CreateAsyncStorage,
DAppMetaData,
SignerWallet,
} from "@thirdweb-dev/wallets";
import React, { useMemo } from "react";

/**
* The possible props for the ThirdwebProvider.
*/
export interface ThirdwebProviderCoreProps<TChains extends Chain[]>
extends ThirdwebSDKProviderProps<TChains> {
extends Omit<ThirdwebSDKProviderProps<TChains>, "signer"> {
/**
* An array of wallets that the dApp supports
* If not provided, will default to Metamask (injected), Coinbase wallet and Device wallet
Expand Down Expand Up @@ -70,6 +71,8 @@ export interface ThirdwebProviderCoreProps<TChains extends Chain[]>
* @defaultValue 15000
*/
autoConnectTimeout?: number;

signerWallet?: WalletConfig<SignerWallet>;
}

export const ThirdwebProviderCore = <TChains extends Chain[]>({
Expand Down Expand Up @@ -153,6 +156,7 @@ export const ThirdwebProviderCore = <TChains extends Chain[]>({
autoConnectTimeout={props.autoConnectTimeout}
clientId={props.clientId}
activeChainSetExplicitly={!!props.activeChain}
signerWallet={props.signerWallet}
>
<ThirdwebSDKProviderWrapper
queryClient={props.queryClient}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
AsyncStorage,
ConnectParams,
CreateAsyncStorage,
SignerWallet,
walletIds,
} from "@thirdweb-dev/wallets";
import { Signer } from "ethers";
Expand Down Expand Up @@ -109,6 +110,7 @@ export function ThirdwebWalletProvider(
autoConnectTimeout?: number;
clientId?: string;
activeChainSetExplicitly: boolean;
signerWallet?: WalletConfig<SignerWallet>;
}>,
) {
const [signer, setSigner] = useState<Signer | undefined>(undefined);
Expand Down Expand Up @@ -265,6 +267,11 @@ export function ThirdwebWalletProvider(

// Auto Connect
useEffect(() => {
// do not auto connect if signerWallet is given
if (props.signerWallet) {
return;
}

if (autoConnectTriggered.current) {
return;
}
Expand Down Expand Up @@ -375,6 +382,7 @@ export function ThirdwebWalletProvider(
activeWallet,
connectionStatus,
autoConnectTimeout,
props.signerWallet,
]);

const connectWallet = useCallback(
Expand Down Expand Up @@ -462,6 +470,33 @@ export function ThirdwebWalletProvider(
};
}, [activeWallet, onWalletDisconnect]);

// connect signerWallet immediately if it's passed
// and disconnect it if it's not passed
const signerConnected = useRef<typeof props.signerWallet>();
useEffect(() => {
if (!props.signerWallet) {
if (signerConnected.current) {
disconnectWallet();
signerConnected.current = undefined;
}
return;
}

if (signerConnected.current === props.signerWallet) {
return;
}

const wallet = createWalletInstance(props.signerWallet);
setConnectedWallet(wallet);
signerConnected.current = props.signerWallet;
}, [
createWalletInstance,
props.supportedWallets,
setConnectedWallet,
props.signerWallet,
disconnectWallet,
]);

return (
<ThirdwebWalletContext.Provider
value={{
Expand Down
15 changes: 13 additions & 2 deletions packages/react/src/evm/providers/thirdweb-provider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,17 @@ import {
import { WalletUIStatesProvider } from "./wallet-ui-states-provider";
import { ConnectModal } from "../../wallet/ConnectWallet/Modal/ConnectModal";
import { ThemeObjectOrType } from "../../design-system";
import { PropsWithChildren } from "react";
import { PropsWithChildren, useMemo } from "react";
import type { Chain, defaultChains } from "@thirdweb-dev/chains";
import { defaultWallets } from "../../wallet/wallets/defaultWallets";
import { CustomThemeProvider } from "../../design-system/CustomThemeProvider";
import { signerWallet } from "../../wallet/wallets/signerWallet";
import { Signer } from "ethers";

interface ThirdwebProviderProps<TChains extends Chain[]>
extends Omit<
ThirdwebProviderCoreProps<TChains>,
"createWalletStorage" | "supportedWallets" | "signer" | "theme"
"createWalletStorage" | "supportedWallets" | "theme"
> {
/**
* Wallets supported by the dApp
Expand All @@ -36,6 +38,8 @@ interface ThirdwebProviderProps<TChains extends Chain[]>
* @defaultValue "dark"
*/
theme?: ThemeObjectOrType;

signer?: Signer;
}

/**
Expand Down Expand Up @@ -64,19 +68,26 @@ export const ThirdwebProvider = <
>({
supportedWallets,
children,
signer,
theme: _theme,
...restProps
}: PropsWithChildren<ThirdwebProviderProps<TChains>>) => {
const wallets: WalletConfig[] = supportedWallets || defaultWallets;
const theme = _theme || "dark";

const signerWalletConfig = useMemo(
() => (signer ? (signerWallet(signer) as WalletConfig<any>) : undefined),
[signer],
);

return (
<WalletUIStatesProvider theme={theme}>
<CustomThemeProvider theme={theme}>
<ThirdwebProviderCore
{...restProps}
theme={typeof theme === "string" ? theme : theme.type}
supportedWallets={wallets}
signerWallet={signerWalletConfig}
>
{children}
<ConnectModal />
Expand Down
19 changes: 19 additions & 0 deletions packages/react/src/wallet/wallets/signerWallet.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { SignerWallet, WalletOptions } from "@thirdweb-dev/wallets";
import { Signer } from "ethers";
import { WalletConfig } from "@thirdweb-dev/react-core";

export const signerWallet = (signer: Signer): WalletConfig<SignerWallet> => {
return {
id: "signerWallet",
meta: {
name: "Signer",
iconURL:
"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHhtbDpzcGFjZT0icHJlc2VydmUiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiPjxwYXRoIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgZmlsbC1ydWxlPSJldmVub2RkIiBkPSJNMTggNWgyYTIgMiAwIDAgMSAyIDJ2MTJhMiAyIDAgMCAxLTIgMkg0YTIgMiAwIDAgMS0yLTJoLjAyN0EyIDIgMCAwIDEgMiAxOC42NzRWNi43NTRhMiAyIDAgMCAxIDEuNDUtMS45MjNsMTItMy40MjhBMiAyIDAgMCAxIDE4IDMuMzI2VjV6bTAgMnY4LjI0NmEyIDIgMCAwIDEtMS40NSAxLjkyM0wxMC4xNCAxOUgyMFY3aC0yek00IDYuNzU0djExLjkybDEyLTMuNDI4VjMuMzI2TDQgNi43NTR6TTE4IDExVjloMnYyaC0yem0tNS0xYTEgMSAwIDEgMSAwLTIgMSAxIDAgMCAxIDAgMnoiIHN0eWxlPSJmaWxsOiByZ2IoMTY5LCAyMDQsIDIyNyk7Ij48L3BhdGg+PC9zdmc+",
},
create: (options: WalletOptions) =>
new SignerWallet({
...options,
signer,
}),
};
};
7 changes: 7 additions & 0 deletions packages/wallets/evm/connectors/signer/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"main": "dist/thirdweb-dev-wallets-evm-connectors-signer.cjs.js",
"module": "dist/thirdweb-dev-wallets-evm-connectors-signer.esm.js",
"browser": {
"./dist/thirdweb-dev-wallets-evm-connectors-signer.esm.js": "./dist/thirdweb-dev-wallets-evm-connectors-signer.browser.esm.js"
}
}
7 changes: 7 additions & 0 deletions packages/wallets/evm/wallets/signer/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"main": "dist/thirdweb-dev-wallets-evm-wallets-signer.cjs.js",
"module": "dist/thirdweb-dev-wallets-evm-wallets-signer.esm.js",
"browser": {
"./dist/thirdweb-dev-wallets-evm-wallets-signer.esm.js": "./dist/thirdweb-dev-wallets-evm-wallets-signer.browser.esm.js"
}
}
14 changes: 14 additions & 0 deletions packages/wallets/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,13 @@
},
"default": "./evm/wallets/ethers/dist/thirdweb-dev-wallets-evm-wallets-ethers.cjs.js"
},
"./evm/wallets/signer": {
"module": {
"browser": "./evm/wallets/signer/dist/thirdweb-dev-wallets-evm-wallets-signer.browser.esm.js",
"default": "./evm/wallets/signer/dist/thirdweb-dev-wallets-evm-wallets-signer.esm.js"
},
"default": "./evm/wallets/signer/dist/thirdweb-dev-wallets-evm-wallets-signer.cjs.js"
},
"./evm/wallets/zerion": {
"module": {
"browser": "./evm/wallets/zerion/dist/thirdweb-dev-wallets-evm-wallets-zerion.browser.esm.js",
Expand Down Expand Up @@ -239,6 +246,13 @@
},
"default": "./evm/connectors/blocto/dist/thirdweb-dev-wallets-evm-connectors-blocto.cjs.js"
},
"./evm/connectors/signer": {
"module": {
"browser": "./evm/connectors/signer/dist/thirdweb-dev-wallets-evm-connectors-signer.browser.esm.js",
"default": "./evm/connectors/signer/dist/thirdweb-dev-wallets-evm-connectors-signer.esm.js"
},
"default": "./evm/connectors/signer/dist/thirdweb-dev-wallets-evm-connectors-signer.cjs.js"
},
"./evm/connectors/zerion": {
"module": {
"browser": "./evm/connectors/zerion/dist/thirdweb-dev-wallets-evm-connectors-zerion.browser.esm.js",
Expand Down
113 changes: 113 additions & 0 deletions packages/wallets/src/evm/connectors/signer/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
import { normalizeChainId } from "../../../lib/wagmi-core";
import { ConnectParams, Connector } from "../../interfaces/connector";
import type { LocalWalletConnectionArgs } from "../../wallets/local-wallet";
import type { Chain } from "@thirdweb-dev/chains";
import type { Signer } from "ethers";
import { providers } from "ethers";
import { getChainProvider } from "@thirdweb-dev/sdk";

export type SignerWalletConnectorOptions = {
chain: Chain;
signer: Signer;
chains: Chain[];
clientId?: string;
secretKey?: string;
};

export class SignerConnector extends Connector<LocalWalletConnectionArgs> {
options: SignerWalletConnectorOptions;
#provider?: providers.Provider;
#signer?: Signer;

constructor(options: SignerWalletConnectorOptions) {
super();
this.options = options;
}

async connect(args: ConnectParams<LocalWalletConnectionArgs>) {
if (args.chainId) {
this.switchChain(args.chainId);
}
const signer = await this.getSigner();
const address = await signer.getAddress();
return address;
}

async disconnect() {
this.#provider = undefined;
this.#signer = undefined;
}

async getAddress(): Promise<string> {
const signer = await this.getSigner();
if (!signer) {
throw new Error("No signer found");
}
return await signer.getAddress();
}

async isConnected(): Promise<boolean> {
try {
const addr = await this.getAddress();
return !!addr;
} catch {
return false;
}
}

async getProvider() {
if (!this.#provider) {
this.#provider = getChainProvider(this.options.chain, {
clientId: this.options.clientId,
secretKey: this.options.secretKey,
});
}
return this.#provider;
}

async getSigner() {
if (!this.#signer) {
const provider = await this.getProvider();
this.#signer = getUpdatedSigner(this.options.signer, provider);
}
return this.#signer;
}

async switchChain(chainId: number): Promise<void> {
const chain = this.options.chains.find((c) => c.chainId === chainId);

if (!chain) {
throw new Error(
`Chain not found for chainId ${chainId}, please add it to the chains property when creating this wallet`,
);
}

this.#provider = getChainProvider(chain, {
clientId: this.options.clientId,
secretKey: this.options.secretKey,
});

this.#signer = getUpdatedSigner(this.options.signer, this.#provider);

this.onChainChanged(chainId);
}

protected onChainChanged = (chainId: number | string) => {
const id = normalizeChainId(chainId);
const unsupported = !this.options.chains.find((c) => c.chainId === id);
this.emit("change", { chain: { id, unsupported } });
};

async setupListeners() {}

updateChains(chains: Chain[]): void {
this.options.chains = chains;
}
}

function getUpdatedSigner(signer: Signer, provider?: providers.Provider) {
if (provider) {
return signer.connect(provider);
}
return signer;
}
1 change: 1 addition & 0 deletions packages/wallets/src/evm/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ export * from "./wallets/ethers";
export * from "./wallets/frame";
export * from "./wallets/injected";
export * from "./wallets/local-wallet";
export * from "./wallets/signer";
export * from "./wallets/magic";
export * from "./wallets/metamask";
export * from "./wallets/phantom";
Expand Down
Loading