UNPKG

@thirdweb-dev/wallets

Version:

<p align="center"> <br /> <a href="https://thirdweb.com"><img src="https://github.com/thirdweb-dev/js/blob/main/legacy_packages/sdk/logo.svg?raw=true" width="200" alt=""/></a> <br /> </p> <h1 align="center">thirdweb Wallet SDK</h1> <p align="center"> <a h

368 lines (341 loc) • 9.8 kB
'use strict'; var chains = require('@thirdweb-dev/chains'); var evm_wallets_abstract_dist_thirdwebDevWalletsEvmWalletsAbstract = require('../evm/wallets/abstract/dist/thirdweb-dev-wallets-evm-wallets-abstract.cjs.dev.js'); var headers = require('./headers-2be346e5.cjs.dev.js'); const PREFIX = "__TW__"; /** * @internal */ class AsyncLocalStorage { constructor(name) { this.name = name; } getItem(key) { return new Promise(res => { res(localStorage.getItem(`${PREFIX}/${this.name}/${key}`)); }); } setItem(key, value) { return new Promise((res, rej) => { try { localStorage.setItem(`${PREFIX}/${this.name}/${key}`, value); res(); } catch (e) { rej(e); } }); } removeItem(key) { return new Promise(res => { localStorage.removeItem(`${PREFIX}/${this.name}/${key}`); res(); }); } } /** * @internal */ function createAsyncLocalStorage(name) { return new AsyncLocalStorage(name); } /** * @internal */ const DEFAULT_DAPP_META = { name: "thirdweb powered dApp", url: "https://thirdweb.com", description: "thirdweb powered dApp", logoUrl: "https://thirdweb.com/favicon.ico", isDarkMode: true }; let walletAnalyticsEnabled = true; /** * Check if Wallet Analytics is enabled or not * * @example * ```ts * import { isWalletAnalyticsEnabled } from '@thirdweb/wallets'; * * const isAnalyticsEnabled = isWalletAnalyticsEnabled(); * ``` * * The Wallet analytics can be used to track: * - Total and Unique users * - Users connected over time * - Type of wallets connected * - Distribution of wallets connected * * You can view these Analytics in the [ThirdWeb Wallet Analytics dashboard](https://thirdweb.com/dashboard/wallets/analytics) * * By default it is enabled. You can disable it by calling `setWalletAnalyticsEnabled(false)` * * ```ts * import { setWalletAnalyticsEnabled } from '@thirdweb/wallets'; * * setWalletAnalyticsEnabled(false); * ``` * */ function isWalletAnalyticsEnabled() { return walletAnalyticsEnabled; } /** * Enable or disable Wallet Analytics * * @example * ```ts * import { setWalletAnalyticsEnabled } from '@thirdweb/wallets'; * * setWalletAnalyticsEnabled(false); * ``` * * The Wallet analytics can be used to track: * - Total and Unique users * - Users connected over time * - Type of wallets connected * - Distribution of wallets connected * * You can view these Analytics in the [ThirdWeb Wallet Analytics dashboard](https://thirdweb.com/dashboard/wallets/analytics) * * By default, The Wallet Analytics is enabled * * You can check if it is enabled or not by calling `isWalletAnalyticsEnabled()` * ```ts * import { isWalletAnalyticsEnabled } from '@thirdweb/wallets'; * * const isAnalyticsEnabled = isWalletAnalyticsEnabled(); * ``` * */ function setWalletAnalyticsEnabled(enabled) { walletAnalyticsEnabled = enabled; } const ANALYTICS_ENDPOINT = "https://c.thirdweb.com/event"; function track(args) { if (!isWalletAnalyticsEnabled()) { return; } const { clientId, walletType, walletAddress, source, action } = args; const body = { source, action, walletAddress, walletType }; // don't block on analytic calls fetch(ANALYTICS_ENDPOINT, { method: "POST", headers: { "Content-Type": "application/json", "x-client-id": clientId, ...headers.getAnalyticsHeaders() }, body: JSON.stringify(body) }); } /* eslint-disable @typescript-eslint/ban-types */ /** * General options required for creating a wallet instance */ /** * The base class for all client-side wallets (web, mobile) in the Wallet SDK. It extends AbstractWallet and adds client side specific logic. * A client side wallet delegates the wallet-specific connection logic to a Connector. * * This wallet is not meant to be used directly, but instead be extended to [build your own wallet](https://portal.thirdweb.com/wallet-sdk/v2/build) * * @abstractWallet */ class AbstractClientWallet extends evm_wallets_abstract_dist_thirdwebDevWalletsEvmWalletsAbstract.AbstractWallet { /** * @internal */ /** * @internal */ getMeta() { return this.constructor.meta; } /** * Creates an returns instance of `AbstractClientWallet` * * @param walletId - A Unique identifier for the wallet ( name of the wallet ) * @param options - Options for creating wallet instance */ constructor(walletId, options) { super(); this.walletId = walletId; this.options = options; this.chains = (options?.chains || chains.defaultChains).map(c => chains.updateChainRPCs(c, options?.clientId)); this.dappMetadata = options?.dappMetadata || DEFAULT_DAPP_META; this.walletStorage = options?.walletStorage || createAsyncLocalStorage(this.walletId); } /** * Returns the Wallet Connector used by the wallet */ /** * auto-connect the wallet if possible * @returns */ async autoConnect(connectOptions) { // remove chainId when auto-connecting to prevent switch-network popup on page load const options = connectOptions ? { ...connectOptions, chainId: undefined } : undefined; return this._connect(true, options); } /** * Connect wallet * @param connectOptions - Options for connecting to the wallet * @returns */ async connect(connectOptions) { this._connectParams = connectOptions; const address = await this._connect(false, connectOptions); if (!address) { throw new Error("Failed to connect to the wallet."); } return address; } /** * @internal * Get the options used for connecting to the wallet * @returns */ getConnectParams() { return this._connectParams; } /** * @internal * Get the options used for creating the wallet instance */ getOptions() { return this.options; } async _connect(isAutoConnect, connectOptions) { const connector = await this.getConnector(); this._subscribeToEvents(connector); const isConnected = await connector.isConnected(); // if already connected, return the address and setup listeners if (isConnected) { const address = await connector.getAddress(); connector.setupListeners(); // ensure that connector is connected to the correct chain if (connectOptions?.chainId) { await connector.switchChain(connectOptions?.chainId); } this.emit("connect", { address, chainId: await this.getChainId() }); this._trackConnection(address); return address; } if (isAutoConnect) { throw new Error("Failed to auto connect to the wallet."); } try { const address = await connector.connect(connectOptions); this._trackConnection(address); return address; } catch (error) { throw new Error(error.message); } } _trackConnection(address) { track({ clientId: this.options?.clientId || "", source: "connectWallet", action: "connect", walletType: this.walletId, walletAddress: address }); } async _subscribeToEvents(connector) { // subscribe to connector for events connector.on("connect", data => { this.emit("connect", { address: data.account, chainId: data.chain?.id }); }); connector.on("change", data => { this.emit("change", { address: data.account, chainId: data.chain?.id }); }); connector.on("message", data => { this.emit("message", data); }); connector.on("disconnect", async () => { this.emit("disconnect"); }); connector.on("error", error => this.emit("error", error)); } /** * Get [ethers Signer](https://docs.ethers.org/v5/api/signer/) object of the connected wallet */ async getSigner() { const connector = await this.getConnector(); if (!connector) { throw new Error("Wallet not connected"); } return await connector.getSigner(); } /** * Disconnect the wallet */ async disconnect() { const connector = await this.getConnector(); if (connector) { await connector.disconnect(); this.emit("disconnect"); connector.removeAllListeners(); } } /** * Switch to different Network/Blockchain in the connected wallet * @param chainId - The chainId of the network to switch to */ async switchChain(chainId) { const connector = await this.getConnector(); if (!connector) { throw new Error("Wallet not connected"); } if (!connector.switchChain) { throw new Error("Wallet does not support switching chains"); } return await connector.switchChain(chainId); } /** * Update the chains supported by the wallet. This is useful if wallet was initialized with some chains and this needs to be updated without re-initializing the wallet */ async updateChains(chains$1) { this.chains = chains$1.map(c => { return chains.updateChainRPCs(c, this.options?.clientId); }); const connector = await this.getConnector(); connector.updateChains(this.chains); } /** * If the wallet uses another "personal wallet" under the hood, return it * * This is only useful for wallets like Safe or Smart Wallet uses a "personal wallet" under the hood to sign transactions. This method returns that wallet */ getPersonalWallet() { return undefined; } } exports.AbstractClientWallet = AbstractClientWallet; exports.AsyncLocalStorage = AsyncLocalStorage; exports.DEFAULT_DAPP_META = DEFAULT_DAPP_META; exports.createAsyncLocalStorage = createAsyncLocalStorage; exports.isWalletAnalyticsEnabled = isWalletAnalyticsEnabled; exports.setWalletAnalyticsEnabled = setWalletAnalyticsEnabled;