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

1,142 lines (1,099 loc) • 33.6 kB
import { _ as _defineProperty } from './defineProperty-7303a112.esm.js'; import { ChainToPublicRpc } from '@paperxyz/sdk-common-utilities'; import { Signer, getDefaultProvider } from 'ethers'; import { defineReadOnly } from 'ethers/lib/utils'; import { getDefaultGasOverrides } from '@thirdweb-dev/sdk'; /** * @internal */ const EMBEDDED_WALLET_PATH = "/sdk/2022-08-12/embedded-wallet"; /** * @internal */ const GET_IFRAME_BASE_URL = () => { if (!!(typeof window !== "undefined" && localStorage.getItem("IS_THIRDWEB_DEV") === "true")) { return window.localStorage.getItem("THIRDWEB_DEV_URL") ?? "http://localhost:3000"; } return `https://embedded-wallet.thirdweb.com`; }; /** * @internal */ const WALLET_USER_DETAILS_LOCAL_STORAGE_NAME = clientId => `thirdwebEwsWalletUserDetails-${clientId}`; /** * @internal */ const WALLET_USER_ID_LOCAL_STORAGE_NAME = clientId => `thirdwebEwsWalletUserId-${clientId}`; /** * @internal */ const AUTH_TOKEN_LOCAL_STORAGE_PREFIX = "walletToken"; /** * @internal */ const AUTH_TOKEN_LOCAL_STORAGE_NAME = clientId => { return `${AUTH_TOKEN_LOCAL_STORAGE_PREFIX}-${clientId}`; }; /** * @internal */ const DEVICE_SHARE_LOCAL_STORAGE_PREFIX = "a"; /** * @internal */ const DEVICE_SHARE_LOCAL_STORAGE_NAME = (clientId, userId) => `${DEVICE_SHARE_LOCAL_STORAGE_PREFIX}-${clientId}-${userId}`; /** * @internal */ const DEVICE_SHARE_LOCAL_STORAGE_NAME_DEPRECATED = clientId => `${DEVICE_SHARE_LOCAL_STORAGE_PREFIX}-${clientId}`; let RecoveryShareManagement = /*#__PURE__*/function (RecoveryShareManagement) { RecoveryShareManagement["USER_MANAGED"] = "USER_MANAGED"; RecoveryShareManagement["CLOUD_MANAGED"] = "AWS_MANAGED"; return RecoveryShareManagement; }({}); let AuthProvider = /*#__PURE__*/function (AuthProvider) { AuthProvider["COGNITO"] = "Cognito"; AuthProvider["GOOGLE"] = "Google"; AuthProvider["EMAIL_OTP"] = "EmailOtp"; AuthProvider["CUSTOM_JWT"] = "CustomJWT"; AuthProvider["CUSTOM_AUTH_ENDPOINT"] = "CustomAuthEndpoint"; AuthProvider["FACEBOOK"] = "Facebook"; AuthProvider["APPLE"] = "Apple"; AuthProvider["PASSKEY"] = "Passkey"; AuthProvider["EXTERNAL_WALLET"] = "ExternalWallet"; AuthProvider["DISCORD"] = "Discord"; return AuthProvider; }({}); /** * @internal */ // TODO: Clean up tech debt of random type Objects // E.g. StoredTokenType is really not used anywhere but it exists as this object for legacy reason // Class constructor types // types for class constructors still a little messy right now. // Open to PRs from whoever sees this and knows of a cleaner way to handle things // Auth Types // Embedded Wallet Types let UserWalletStatus = /*#__PURE__*/function (UserWalletStatus) { UserWalletStatus["LOGGED_OUT"] = "Logged Out"; UserWalletStatus["LOGGED_IN_WALLET_UNINITIALIZED"] = "Logged In, Wallet Uninitialized"; UserWalletStatus["LOGGED_IN_NEW_DEVICE"] = "Logged In, New Device"; UserWalletStatus["LOGGED_IN_WALLET_INITIALIZED"] = "Logged In, Wallet Initialized"; return UserWalletStatus; }({}); /** * @internal */ // ! Types seem repetitive, but the name should identify which goes where // this is the return type from the EmbeddedWallet Class getUserWalletStatus method iframe call // this is the return type from the EmbeddedWallet Class getUserWalletStatus method const data = new Map(); class LocalStorage { constructor(_ref) { let { clientId } = _ref; this.isSupported = typeof window !== "undefined" && !!window.localStorage; this.clientId = clientId; } async getItem(key) { if (this.isSupported) { return window.localStorage.getItem(key); } else { return data.get(key) ?? null; } } async setItem(key, value) { if (this.isSupported) { return window.localStorage.setItem(key, value); } else { data.set(key, value); } } async removeItem(key) { const item = await this.getItem(key); if (this.isSupported && item) { window.localStorage.removeItem(key); return true; } return false; } async saveAuthCookie(cookie) { await this.setItem(AUTH_TOKEN_LOCAL_STORAGE_NAME(this.clientId), cookie); } async getAuthCookie() { return this.getItem(AUTH_TOKEN_LOCAL_STORAGE_NAME(this.clientId)); } async removeAuthCookie() { return this.removeItem(AUTH_TOKEN_LOCAL_STORAGE_NAME(this.clientId)); } async saveDeviceShare(share, userId) { await this.saveWalletUserId(userId); await this.setItem(DEVICE_SHARE_LOCAL_STORAGE_NAME(this.clientId, userId), share); } async getDeviceShare() { const userId = await this.getWalletUserId(); if (userId) { return this.getItem(DEVICE_SHARE_LOCAL_STORAGE_NAME(this.clientId, userId)); } return null; } async removeDeviceShare() { const userId = await this.getWalletUserId(); if (userId) { return this.removeItem(DEVICE_SHARE_LOCAL_STORAGE_NAME(this.clientId, userId)); } return false; } async getWalletUserId() { return this.getItem(WALLET_USER_ID_LOCAL_STORAGE_NAME(this.clientId)); } async saveWalletUserId(userId) { await this.setItem(WALLET_USER_ID_LOCAL_STORAGE_NAME(this.clientId), userId); } async removeWalletUserId() { return this.removeItem(WALLET_USER_ID_LOCAL_STORAGE_NAME(this.clientId)); } } function sleep(seconds) { return new Promise(resolve => { setTimeout(resolve, seconds * 1000); }); } const iframeBaseStyle = { height: "100%", width: "100%", border: "none", backgroundColor: "transparent", colorScheme: "light", position: "fixed", top: "0px", right: "0px", zIndex: "2147483646", display: "none" }; // Global var to help track iframe state const isIframeLoaded = new Map(); class IframeCommunicator { constructor(_ref) { let { link, iframeId, container = document.body, iframeStyles, onIframeInitialize } = _ref; _defineProperty(this, "POLLING_INTERVAL_SECONDS", 1.4); this.iframeBaseUrl = GET_IFRAME_BASE_URL(); // Creating the IFrame element for communication let iframe = document.getElementById(iframeId); const hrefLink = new URL(link); const sdkVersion = "2.5.39"; hrefLink.searchParams.set("sdkVersion", sdkVersion); if (!iframe || iframe.src !== hrefLink.href) { // ! Do not update the hrefLink here or it'll cause multiple re-renders if (!iframe) { iframe = document.createElement("iframe"); const mergedIframeStyles = { ...iframeBaseStyle, ...iframeStyles }; Object.assign(iframe.style, mergedIframeStyles); iframe.setAttribute("id", iframeId); iframe.setAttribute("fetchpriority", "high"); container.appendChild(iframe); } iframe.src = hrefLink.href; iframe.setAttribute("data-version", sdkVersion); const onIframeLoaded = event => { if (event.data.eventType === "ewsIframeLoaded") { window.removeEventListener("message", onIframeLoaded); if (!iframe) { console.warn("thirdweb Iframe not found"); return; } this.onIframeLoadHandler(iframe, onIframeInitialize)(); } }; window.addEventListener("message", onIframeLoaded); } this.iframe = iframe; } async onIframeLoadedInitVariables() { return {}; } onIframeLoadHandler(iframe, onIframeInitialize) { return async () => { const promise = new Promise(async (res, rej) => { const channel = new MessageChannel(); channel.port1.onmessage = event => { const { data } = event; channel.port1.close(); if (!data.success) { return rej(new Error(data.error)); } isIframeLoaded.set(iframe.src, true); if (onIframeInitialize) { onIframeInitialize(); } return res(true); }; const INIT_IFRAME_EVENT = "initIframe"; iframe?.contentWindow?.postMessage( // ? We initialise the iframe with a bunch // of useful information so that we don't have to pass it // through in each of the future call. This would be where we do it. { eventType: INIT_IFRAME_EVENT, data: await this.onIframeLoadedInitVariables() }, this.iframeBaseUrl, [channel.port2]); }); await promise; }; } async call(_ref2) { let { procedureName, params, showIframe = false } = _ref2; while (!isIframeLoaded.get(this.iframe.src)) { await sleep(this.POLLING_INTERVAL_SECONDS); } if (showIframe) { this.iframe.style.display = "block"; // magic number to let the display render before performing the animation of the modal in await sleep(0.005); } const promise = new Promise((res, rej) => { const channel = new MessageChannel(); channel.port1.onmessage = async event => { const { data } = event; channel.port1.close(); if (showIframe) { // magic number to let modal fade out before hiding it await sleep(0.1); this.iframe.style.display = "none"; } if (!data.success) { rej(new Error(data.error)); } else { res(data.data); } }; this.iframe.contentWindow?.postMessage({ eventType: procedureName, data: params }, this.iframeBaseUrl, [channel.port2]); }); return promise; } /** * This has to be called by any iframe that will be removed from the DOM. * Use to make sure that we reset the global loaded state of the particular iframe.src */ destroy() { isIframeLoaded.delete(this.iframe.src); } } class EmbeddedWalletIframeCommunicator extends IframeCommunicator { constructor(_ref) { let { clientId, customizationOptions } = _ref; super({ iframeId: EMBEDDED_WALLET_IFRAME_ID, link: createEmbeddedWalletIframeLink({ clientId, path: EMBEDDED_WALLET_PATH, queryParams: customizationOptions }).href, container: document.body }); this.clientId = clientId; } async onIframeLoadedInitVariables() { const localStorage = new LocalStorage({ clientId: this.clientId }); return { authCookie: await localStorage.getAuthCookie(), deviceShareStored: await localStorage.getDeviceShare(), walletUserId: await localStorage.getWalletUserId(), clientId: this.clientId }; } } // This is the URL and ID tag of the iFrame that we communicate with function createEmbeddedWalletIframeLink(_ref2) { let { clientId, path, queryParams } = _ref2; const embeddedWalletUrl = new URL(`${path}`, GET_IFRAME_BASE_URL()); if (queryParams) { for (const queryKey of Object.keys(queryParams)) { embeddedWalletUrl.searchParams.set(queryKey, queryParams[queryKey]?.toString() || ""); } } embeddedWalletUrl.searchParams.set("clientId", clientId); return embeddedWalletUrl; } const EMBEDDED_WALLET_IFRAME_ID = "thirdweb-embedded-wallet-iframe"; class AbstractLogin { /** * Used to manage the user's auth states. This should not be instantiated directly. * Call {@link EmbeddedWalletSdk.auth} instead. * */ constructor(_ref) { let { querier, preLogin, postLogin, clientId } = _ref; this.LoginQuerier = querier; this.preLogin = preLogin; this.postLogin = postLogin; this.clientId = clientId; } async sendEmailLoginOtp(_ref2) { let { email } = _ref2; await this.preLogin(); const result = await this.LoginQuerier.call({ procedureName: "sendThirdwebEmailLoginOtp", params: { email } }); return result; } async sendSmsLoginOtp(_ref3) { let { phoneNumber } = _ref3; await this.preLogin(); const result = await this.LoginQuerier.call({ procedureName: "sendThirdwebSmsLoginOtp", params: { phoneNumber } }); return result; } } class BaseLogin extends AbstractLogin { constructor() { super(...arguments); _defineProperty(this, "closeWindow", _ref => { let { isWindowOpenedByFn, win, closeOpenedWindow } = _ref; if (isWindowOpenedByFn) { win?.close(); } else { if (win && closeOpenedWindow) { closeOpenedWindow(win); } else if (win) { win.close(); } } }); } async getOauthLoginUrl(authProvider) { const result = await this.LoginQuerier.call({ procedureName: "getHeadlessOauthLoginLink", params: { authProvider } }); return result; } async loginWithModal() { await this.preLogin(); const result = await this.LoginQuerier.call({ procedureName: "loginWithThirdwebModal", params: undefined, showIframe: true }); return this.postLogin(result); } async loginWithEmailOtp(_ref2) { let { email } = _ref2; await this.preLogin(); const result = await this.LoginQuerier.call({ procedureName: "loginWithThirdwebModal", params: { email }, showIframe: true }); return this.postLogin(result); } getOauthPopUpSizing(authProvider) { switch (authProvider) { case AuthProvider.FACEBOOK: return "width=715, height=555"; default: return "width=350, height=500"; } } async loginWithOauth(args) { let win = args?.openedWindow; let isWindowOpenedByFn = false; if (!win) { win = window.open("", "Login", this.getOauthPopUpSizing(args.oauthProvider)); isWindowOpenedByFn = true; } if (!win) { throw new Error("Something went wrong opening pop-up"); } // logout the user // fetch the url to open the login window from iframe const [{ loginLink }] = await Promise.all([this.getOauthLoginUrl(args.oauthProvider), this.preLogin()]); win.location.href = loginLink; // listen to result from the login window const result = await new Promise((resolve, reject) => { // detect when the user closes the login window const pollTimer = window.setInterval(async () => { if (!win) { return; } if (win.closed) { clearInterval(pollTimer); window.removeEventListener("message", messageListener); reject(new Error("User closed login window")); } }, 1000); const messageListener = async event => { if (event.origin !== GET_IFRAME_BASE_URL()) { return; } if (typeof event.data !== "object") { reject(new Error("Invalid event data")); return; } switch (event.data.eventType) { case "userLoginSuccess": { window.removeEventListener("message", messageListener); clearInterval(pollTimer); this.closeWindow({ isWindowOpenedByFn, win, closeOpenedWindow: args?.closeOpenedWindow }); if (event.data.authResult) { resolve(event.data.authResult); } break; } case "userLoginFailed": { window.removeEventListener("message", messageListener); clearInterval(pollTimer); this.closeWindow({ isWindowOpenedByFn, win, closeOpenedWindow: args?.closeOpenedWindow }); reject(new Error(event.data.error)); break; } case "injectDeveloperClientId": { win?.postMessage({ eventType: "injectDeveloperClientIdResult", developerClientId: this.clientId, authOption: args.oauthProvider }, GET_IFRAME_BASE_URL()); break; } } }; window.addEventListener("message", messageListener); }); return this.postLogin({ storedToken: { ...result.storedToken, shouldStoreCookieString: true }, walletDetails: { ...result.walletDetails, isIframeStorageEnabled: false } }); } async loginWithCustomJwt(_ref3) { let { encryptionKey, jwt } = _ref3; await this.preLogin(); const result = await this.LoginQuerier.call({ procedureName: "loginWithCustomJwt", params: { encryptionKey, jwt } }); return this.postLogin(result); } async loginWithCustomAuthEndpoint(_ref4) { let { encryptionKey, payload } = _ref4; await this.preLogin(); const result = await this.LoginQuerier.call({ procedureName: "loginWithCustomAuthEndpoint", params: { encryptionKey, payload } }); return this.postLogin(result); } async verifyEmailLoginOtp(_ref5) { let { email, otp, recoveryCode } = _ref5; const result = await this.LoginQuerier.call({ procedureName: "verifyThirdwebEmailLoginOtp", params: { email, otp, recoveryCode } }); return this.postLogin(result); } async verifySmsLoginOtp(_ref6) { let { phoneNumber, otp, recoveryCode } = _ref6; const result = await this.LoginQuerier.call({ procedureName: "verifyThirdwebSmsLoginOtp", params: { phoneNumber, otp, recoveryCode } }); return this.postLogin(result); } } class Auth { /** * Used to manage the user's auth states. This should not be instantiated directly. * Call {@link EmbeddedWalletSdk.auth} instead. */ constructor(_ref) { let { clientId, querier, onAuthSuccess } = _ref; this.clientId = clientId; this.AuthQuerier = querier; this.localStorage = new LocalStorage({ clientId }); this.onAuthSuccess = onAuthSuccess; this.BaseLogin = new BaseLogin({ postLogin: async result => { return this.postLogin(result); }, preLogin: async () => { await this.preLogin(); }, querier: querier, clientId }); } async preLogin() { await this.logout(); } async postLogin(_ref2) { let { storedToken, walletDetails } = _ref2; if (storedToken.shouldStoreCookieString) { await this.localStorage.saveAuthCookie(storedToken.cookieString); } const initializedUser = await this.onAuthSuccess({ storedToken, walletDetails }); return initializedUser; } /** * Used to log the user into their thirdweb wallet on your platform via a myriad of auth providers * * @example * ```typescript * const thirdwebEmbeddedWallet = new EmbeddedWalletSdk({clientId: "YOUR_CLIENT_ID", chain: "Polygon"}) * try { * const user = await thirdwebEmbeddedWallet.auth.loginWithModal(); * // user is now logged in * } catch (e) { * // User closed modal or something else went wrong during the authentication process * console.error(e) * } * ``` * * @returns `{{user: InitializedUser}}` An InitializedUser object. See {@link EmbeddedWalletSdk.getUser} for more */ async loginWithModal() { return this.BaseLogin.loginWithModal(); } /** * Used to log the user into their thirdweb wallet using email OTP * * @example * ```typescript * // Basic Flow * const thirdwebEmbeddedWallet = new EmbeddedWalletSdk({clientId: "", chain: "Polygon"}); * try { * // prompts user to enter the code they received * const user = await thirdwebEmbeddedWallet.auth.loginWithThirdwebEmailOtp({ email : "you@example.com" }); * // user is now logged in * } catch (e) { * // User closed the OTP modal or something else went wrong during the authentication process * console.error(e) * } * ``` * * @param args - args.email: We will send the email an OTP that needs to be entered in order for them to be logged in. * @returns `{{user: InitializedUser}}` An InitializedUser object. See {@link EmbeddedWalletSdk.getUser} for more */ async loginWithEmailOtp(args) { return this.BaseLogin.loginWithEmailOtp(args); } async loginWithCustomJwt(args) { return this.BaseLogin.loginWithCustomJwt(args); } async loginWithCustomAuthEndpoint(args) { return this.BaseLogin.loginWithCustomAuthEndpoint(args); } async loginWithOauth(args) { return this.BaseLogin.loginWithOauth(args); } /** * A headless way to send the users at the passed email an OTP code. * You need to then call {@link Auth.verifyEmailLoginOtp} in order to complete the login process * * @example * ```typescript * const thirdwebEmbeddedWallet = new EmbeddedWalletSdk({clientId: "", chain: "Polygon"}); * // sends user an OTP code * try { * await thirdwebEmbeddedWallet.auth.sendEmailLoginOtp({ email : "you@example.com" }); * } catch(e) { * // Error Sending user's email an OTP code * console.error(e); * } * * // Then when your user is ready to verify their OTP * try { * const user = await thirdwebEmbeddedWallet.auth.verifyEmailLoginOtp({ email: "you@example.com", otp: "6-DIGIT_CODE_HERE" }); * } catch(e) { * // Error verifying the OTP code * console.error(e) * } * ``` * * @param param0 - param0.email We will send the email an OTP that needs to be entered in order for them to be logged in. * @returns `{{ isNewUser: boolean }}` IsNewUser indicates if the user is a new user to your platform */ async sendEmailLoginOtp(_ref3) { let { email } = _ref3; return this.BaseLogin.sendEmailLoginOtp({ email }); } async sendSmsLoginOtp(_ref4) { let { phoneNumber } = _ref4; return this.BaseLogin.sendSmsLoginOtp({ phoneNumber }); } /** * Used to verify the otp that the user receives from thirdweb * * See {@link Auth.sendEmailLoginOtp} for how the headless call flow looks like. Simply swap out the calls to `loginWithThirdwebEmailOtp` with `verifyThirdwebEmailLoginOtp` * * @param args - props.email We will send the email an OTP that needs to be entered in order for them to be logged in. * props.otp The code that the user received in their email * @returns `{{user: InitializedUser}}` An InitializedUser object containing the user's status, wallet, authDetails, and more */ async verifyEmailLoginOtp(args) { return this.BaseLogin.verifyEmailLoginOtp(args); } async verifySmsLoginOtp(args) { return this.BaseLogin.verifySmsLoginOtp(args); } /** * Logs any existing user out of their wallet. * @returns `{{success: boolean}}` true if a user is successfully logged out. false if there's no user currently logged in. */ async logout() { const { success } = await this.AuthQuerier.call({ procedureName: "logout", params: undefined }); const isRemoveAuthCookie = await this.localStorage.removeAuthCookie(); const isRemoveUserId = await this.localStorage.removeWalletUserId(); return { success: success || isRemoveAuthCookie || isRemoveUserId }; } } class EthersSigner extends Signer { constructor(_ref) { let { provider, clientId, querier } = _ref; super(); _defineProperty(this, "DEFAULT_ETHEREUM_CHAIN_ID", 5); this.clientId = clientId; this.querier = querier; // we try to extract a url if possible this.endpoint = provider.connection?.url; defineReadOnly(this, "provider", provider); } async getAddress() { const { address } = await this.querier.call({ procedureName: "getAddress", params: undefined }); return address; } async signMessage(message) { const { signedMessage } = await this.querier.call({ procedureName: "signMessage", params: { message, chainId: (await this.provider?.getNetwork())?.chainId ?? this.DEFAULT_ETHEREUM_CHAIN_ID, rpcEndpoint: this.endpoint } }); return signedMessage; } async signTransaction(transaction) { const { signedTransaction } = await this.querier.call({ procedureName: "signTransaction", params: { transaction, chainId: (await this.provider?.getNetwork())?.chainId ?? this.DEFAULT_ETHEREUM_CHAIN_ID, rpcEndpoint: this.endpoint } }); return signedTransaction; } async sendTransaction(transaction) { if (!this.provider) { throw new Error("Provider not found"); } const gas = await getDefaultGasOverrides(this.provider); const txWithGas = { ...gas, ...transaction }; return super.sendTransaction(txWithGas); } async _signTypedData(domain, types, message) { const { signedTypedData } = await this.querier.call({ procedureName: "signTypedDataV4", params: { domain, types, message, chainId: (await this.provider?.getNetwork())?.chainId ?? this.DEFAULT_ETHEREUM_CHAIN_ID, rpcEndpoint: this.endpoint } }); return signedTypedData; } connect(provider) { return new EthersSigner({ clientId: this.clientId, provider, querier: this.querier }); } } class EmbeddedWallet { /** * Not meant to be initialized directly. Call {@link initializeUser} to get an instance */ constructor(_ref) { let { clientId, chain, querier } = _ref; this.clientId = clientId; this.chain = chain; this.walletManagerQuerier = querier; this.localStorage = new LocalStorage({ clientId }); } /** * @internal * Used to set-up the user device in the case that they are using incognito * @returns `{walletAddress : string }` The user's wallet details */ async postWalletSetUp(_ref2) { let { deviceShareStored, walletAddress, isIframeStorageEnabled, walletUserId } = _ref2; if (!isIframeStorageEnabled) { await this.localStorage.saveDeviceShare(deviceShareStored, walletUserId); } return { walletAddress }; } /** * @internal * Gets the various status states of the user * @example * ```typescript * const userStatus = await Paper.getUserWalletStatus(); * switch (userStatus.status) { * case UserWalletStatus.LOGGED_OUT: { * // User is logged out, call one of the auth methods on Paper.auth to authenticate the user * break; * } * case UserWalletStatus.LOGGED_IN_WALLET_UNINITIALIZED: { * // User is logged in, but does not have a wallet associated with it * // you also have access to the user's details * userStatus.user.authDetails; * break; * } * case UserWalletStatus.LOGGED_IN_NEW_DEVICE: { * // User is logged in and created a wallet already, but is missing the device shard * // You have access to: * userStatus.user.authDetails; * userStatus.user.walletAddress; * break; * } * case UserWalletStatus.LOGGED_IN_WALLET_INITIALIZED: { * // user is logged in and wallet is all set up. * // You have access to: * userStatus.user.authDetails; * userStatus.user.walletAddress; * userStatus.user.wallet; * break; * } *} *``` * @returns `{GetUserWalletStatusFnReturnType}` an object to containing various information on the user statuses */ async getUserWalletStatus() { const userStatus = await this.walletManagerQuerier.call({ procedureName: "getUserStatus", params: undefined }); if (userStatus.status === UserWalletStatus.LOGGED_IN_WALLET_INITIALIZED) { return { status: UserWalletStatus.LOGGED_IN_WALLET_INITIALIZED, ...userStatus.user, wallet: this }; } else if (userStatus.status === UserWalletStatus.LOGGED_IN_NEW_DEVICE) { return { status: UserWalletStatus.LOGGED_IN_WALLET_UNINITIALIZED, ...userStatus.user }; } else if (userStatus.status === UserWalletStatus.LOGGED_IN_WALLET_UNINITIALIZED) { return { status: UserWalletStatus.LOGGED_IN_WALLET_UNINITIALIZED, ...userStatus.user }; } else { // Logged out return { status: userStatus.status }; } } /** * Switches the chain that the user wallet is currently on. * * @example * ```typescript * // user wallet will be set to Polygon * const Paper = new ThirdwebEmbeddedWalletSdk({clientId: "", chain: "Polygon"}); * const user = await Paper.initializeUser(); * // Switch the user wallet to Mumbai * await user.wallet.setChain({ chain: "Mumbai" }); * ``` * @param param0 - The chain that we are changing the user wallet too */ async setChain(_ref3) { let { chain } = _ref3; this.chain = chain; } /** * Returns an Ethers.Js compatible signer that you can use in conjunction with the rest of dApp * @example * ```typescript * const Paper = new ThirdwebEmbeddedWalletSdk({clientId: "", chain: "Polygon"}); * const user = await Paper.getUser(); * if (user.status === UserStatus.LOGGED_IN_WALLET_INITIALIZED) { * // returns a signer on the Polygon mainnet * const signer = await user.getEthersJsSigner(); * // returns a signer on the specified RPC endpoints * const signer = await user.getEthersJsSigner({rpcEndpoint: "https://eth-rpc.gateway.pokt.network"}); * } * ``` * @param network - object with the rpc url where calls will be routed through * @throws If attempting to call the function without the user wallet initialize on their current device. This should never happen if call {@link ThirdwebEmbeddedWalletSdk.initializeUser} before accessing this function * @returns A signer that is compatible with Ether.js. Defaults to the public rpc on the chain specified when initializing the {@link ThirdwebEmbeddedWalletSdk} instance */ async getEthersJsSigner(network) { const signer = new EthersSigner({ clientId: this.clientId, provider: getDefaultProvider(network?.rpcEndpoint ?? ChainToPublicRpc[this.chain]), querier: this.walletManagerQuerier }); return signer; } } class EmbeddedWalletSdk { /** * Used to manage the Auth state of the user. */ isClientIdLegacyPaper(clientId) { if (clientId.indexOf("-") > 0 && clientId.length === 36) { return true; } else { return false; } } /** * @example * `const thirdwebEmbeddedWallet = new EmbeddedWalletSdk({ clientId: "", chain: "Goerli" });` * @param param0 - EmbeddedWalletConstructorType */ constructor(_ref) { let { clientId, chain, styles, onAuthSuccess } = _ref; if (this.isClientIdLegacyPaper(clientId)) { throw new Error("You are using a legacy clientId. Please use the clientId found on the thirdweb dashboard settings page"); } this.clientId = clientId; this.querier = new EmbeddedWalletIframeCommunicator({ clientId, customizationOptions: styles }); this.wallet = new EmbeddedWallet({ clientId, chain, querier: this.querier }); this.auth = new Auth({ clientId, querier: this.querier, onAuthSuccess: async authResult => { onAuthSuccess?.(authResult); await this.wallet.postWalletSetUp({ ...authResult.walletDetails, walletUserId: authResult.storedToken.authDetails.userWalletId }); await this.querier.call({ procedureName: "initIframe", params: { deviceShareStored: authResult.walletDetails.deviceShareStored, clientId: this.clientId, walletUserId: authResult.storedToken.authDetails.userWalletId, authCookie: authResult.storedToken.cookieString } }); return { user: { status: UserWalletStatus.LOGGED_IN_WALLET_INITIALIZED, authDetails: authResult.storedToken.authDetails, wallet: this.wallet, walletAddress: authResult.walletDetails.walletAddress } }; } }); } /** * Gets the usr if they are logged in * @example * ```js * const user = await thirdwebEmbeddedWallet.getUser(); * switch (user.status) { * case UserWalletStatus.LOGGED_OUT: { * // User is logged out, call one of the auth methods on thirdwebEmbeddedWallet.auth to authenticate the user * break; * } * case UserWalletStatus.LOGGED_IN_WALLET_INITIALIZED: { * // user is logged in and wallet is all set up. * // You have access to: * user.status; * user.authDetails; * user.walletAddress; * user.wallet; * break; * } * } * ``` * @returns GetUser - an object to containing various information on the user statuses */ async getUser() { return this.wallet.getUserWalletStatus(); } } export { AUTH_TOKEN_LOCAL_STORAGE_NAME as A, DEVICE_SHARE_LOCAL_STORAGE_NAME as D, EmbeddedWalletSdk as E, RecoveryShareManagement as R, UserWalletStatus as U, WALLET_USER_DETAILS_LOCAL_STORAGE_NAME as W, DEVICE_SHARE_LOCAL_STORAGE_NAME_DEPRECATED as a, WALLET_USER_ID_LOCAL_STORAGE_NAME as b, AuthProvider as c };