UNPKG

@perawallet/connect

Version:

JavaScript SDK for integrating Pera Wallet to web applications.

241 lines (202 loc) 7.21 kB
import PeraWalletConnectError from "../util/PeraWalletConnectError"; import {waitForElementCreatedAtShadowDOM} from "../util/dom/domUtils"; import {generatePeraWalletConnectDeepLink} from "../util/peraWalletUtils"; export type PERA_CONNECT_MODAL_VIEWS = "default" | "download-pera"; export interface PeraWalletModalConfig { isWebWalletAvailable: boolean; shouldDisplayNewBadge: boolean; shouldUseSound: boolean; promoteMobile?: boolean; compactMode?: boolean; singleAccount?: boolean; selectedAccount?: string; isInWebview?: boolean; } // The ID of the wrapper element for PeraWalletConnectModal const PERA_WALLET_CONNECT_MODAL_ID = "pera-wallet-connect-modal-wrapper"; // The ID of the wrapper element for PeraWalletRedirectModal const PERA_WALLET_REDIRECT_MODAL_ID = "pera-wallet-redirect-modal-wrapper"; // The ID of the wrapper element for PeraWalletSignTxnToast const PERA_WALLET_SIGN_TXN_TOAST_ID = "pera-wallet-sign-txn-toast-wrapper"; // The ID of the wrapper element for PeraWalletSignTxnModal const PERA_WALLET_SIGN_TXN_MODAL_ID = "pera-wallet-sign-txn-modal-wrapper"; // The ID of the Pera wallet iframe const PERA_WALLET_IFRAME_ID = "pera-wallet-iframe"; // The classname of Pera wallet modal const PERA_WALLET_MODAL_CLASSNAME = "pera-wallet-modal"; // The classname of Web Wallet IFrame const PERA_WALLET_WEB_WALLET_IFRAME_CLASSNAME = "pera-wallet-connect-modal-desktop-mode__web-wallet-iframe"; /** * Creates a Div element with the given ID and appends it to the DOM. * @param modalId string * * @returns HTMLDivElement */ function createModalWrapperOnDOM(modalId: string) { const wrapper = document.createElement("div"); wrapper.setAttribute("id", modalId); document.body.appendChild(wrapper); return wrapper; } /** * Creates a modal wrapper on the DOM and renders a PeraWalletConnectModal instance on it. * @param modalConfig PeraWalletModalConfig * * @returns VoidFunction */ function openPeraWalletConnectModal(modalConfig: PeraWalletModalConfig) { return (uri: string) => { const { isWebWalletAvailable, shouldDisplayNewBadge, shouldUseSound, compactMode, promoteMobile, singleAccount, selectedAccount, isInWebview } = modalConfig; if (isInWebview) { const deepLink = generatePeraWalletConnectDeepLink(uri, {singleAccount, selectedAccount}); window.open(deepLink, "_blank"); } else if (!document.getElementById(PERA_WALLET_CONNECT_MODAL_ID)) { const root = createModalWrapperOnDOM(PERA_WALLET_CONNECT_MODAL_ID); const newURI = `${uri}&algorand=true`; root.innerHTML = `<pera-wallet-connect-modal uri="${newURI}" is-web-wallet-avaliable="${isWebWalletAvailable}" should-display-new-badge="${shouldDisplayNewBadge}" should-use-sound="${shouldUseSound}" compact-mode="${compactMode}" promote-mobile="${promoteMobile}" single-account="${singleAccount}" selected-account="${selectedAccount || ''}" is-in-webview="${isInWebview || false}"></pera-wallet-connect-modal>`; } }; } /** * Adds a listener to the close button of the given modal. * * @param modalId string * @param onClose VoidFunction * * @returns {void} */ function setupPeraWalletConnectModalCloseListener( modalId: string, onClose: VoidFunction ) { const peraWalletConnectModalWrapper = document.getElementById(modalId); const peraWalletConnectModal = peraWalletConnectModalWrapper ?.querySelector(modalId.replace("-wrapper", "")) ?.shadowRoot?.querySelector(`.${PERA_WALLET_MODAL_CLASSNAME}`); const closeButton = peraWalletConnectModal ?.querySelector("pera-wallet-modal-header") ?.shadowRoot?.getElementById("pera-wallet-modal-header-close-button"); closeButton?.addEventListener("click", () => { onClose(); removeModalWrapperFromDOM(modalId); }); } /** * Creates a PeraWalletRedirectModal instance and renders it on the DOM. * * @returns {void} */ function openPeraWalletRedirectModal() { const root = createModalWrapperOnDOM(PERA_WALLET_REDIRECT_MODAL_ID); root.innerHTML = "<pera-wallet-redirect-modal></pera-wallet-redirect-modal>"; } /** * Creates a PeraWalletSignTxnModal instance and renders it on the DOM. * * @returns {Promise<Element>} */ function openPeraWalletSignTxnModal({isCompactMode}: {isCompactMode?: boolean}) { const root = createModalWrapperOnDOM(PERA_WALLET_SIGN_TXN_MODAL_ID); root.innerHTML = `<pera-wallet-sign-txn-modal compact-mode=${isCompactMode}></pera-wallet-sign-txn-modal>`; const signTxnModal = root.querySelector("pera-wallet-sign-txn-modal"); return signTxnModal ? waitForElementCreatedAtShadowDOM( signTxnModal, "pera-wallet-sign-txn-modal__body__content" ) : Promise.reject(); } /** * Close the PeraWalletSignTxnModal instance and remove it from the DOM. * @param rejectPromise * * @returns {void} */ function closePeraWalletSignTxnModal(rejectPromise?: (error: any) => void) { removeModalWrapperFromDOM(PERA_WALLET_SIGN_TXN_MODAL_ID); if (rejectPromise) { rejectPromise( new PeraWalletConnectError( { type: "SIGN_TXN_CANCELLED" }, "Transaction sign is cancelled" ) ); } } /** * Creates a PeraWalletSignTxnToast instance and renders it on the DOM. * * @returns {void} */ function openPeraWalletSignTxnToast() { const root = createModalWrapperOnDOM(PERA_WALLET_SIGN_TXN_TOAST_ID); root.innerHTML = "<pera-wallet-sign-txn-toast></pera-wallet-sign-txn-toast>"; } /** * Close the PeraWalletSignTxnToast instance and remove it from the DOM. * * @returns {void} */ function closePeraWalletSignTxnToast() { removeModalWrapperFromDOM(PERA_WALLET_SIGN_TXN_TOAST_ID); } /** * Removes the modal wrapper with given ID from the DOM. * @param modalId string * * @returns {void} */ function removeModalWrapperFromDOM(modalId: string) { const wrapper = document.getElementById(modalId); if (wrapper) { wrapper.remove(); } } /** * Return the close button element in the header as a result * @param type "connect" | "sign-txn" * * @returns HTMLElement | null | undefined */ function getHeaderCloseButton(type: "connect" | "sign-txn") { const modalId = type === "connect" ? PERA_WALLET_CONNECT_MODAL_ID : PERA_WALLET_SIGN_TXN_MODAL_ID; const peraWalletConnectModal = document .getElementById(modalId) ?.querySelector(modalId.replace("-wrapper", "")) ?.shadowRoot?.querySelector(`.${PERA_WALLET_MODAL_CLASSNAME}`); const closeButton = peraWalletConnectModal ?.querySelector("pera-wallet-modal-header") ?.shadowRoot?.getElementById("pera-wallet-modal-header-close-button"); return closeButton; } export { PERA_WALLET_CONNECT_MODAL_ID, PERA_WALLET_REDIRECT_MODAL_ID, PERA_WALLET_SIGN_TXN_TOAST_ID, PERA_WALLET_SIGN_TXN_MODAL_ID, PERA_WALLET_MODAL_CLASSNAME, PERA_WALLET_WEB_WALLET_IFRAME_CLASSNAME, PERA_WALLET_IFRAME_ID, openPeraWalletConnectModal, setupPeraWalletConnectModalCloseListener, openPeraWalletRedirectModal, openPeraWalletSignTxnToast, closePeraWalletSignTxnToast, removeModalWrapperFromDOM, openPeraWalletSignTxnModal, closePeraWalletSignTxnModal, getHeaderCloseButton };