import { WalletAdapterNetwork } from "@solana/wallet-adapter-base"; import { NPM_VERSION } from "./index.js"; import { TipLinkEmbed } from "./embed.js"; import { TipLinkWalletAdapter } from "./index.js"; import type { TIPLINK_BUILD_ENV_TYPE } from "./interfaces.js"; export const getTipLinkUrl = (buildEnv: TIPLINK_BUILD_ENV_TYPE): string => { switch (buildEnv) { case "production": return "https://tiplink.io"; case "staging": return "https://staging.tiplink.io"; case "development": return "https://dev.tiplink.io"; case "adapter": return "https://adapter.tiplink.io"; case "local": return "http://localhost:3000"; } }; export function getCloseButtonUrl(buildEnv: TIPLINK_BUILD_ENV_TYPE): string { const logoUrl = new URL( "adapter-popup-close-icon.svg", getTipLinkUrl(buildEnv) ); return logoUrl.toString(); } const iframePath = "embedded_wallet"; export function iFrameUrl({ buildEnv, clientId, tipLinkAutoConnect, theme, hideDraggableWidget, autoConnect, walletAdapterNetwork, hideWalletOnboard, }: { buildEnv: TIPLINK_BUILD_ENV_TYPE; clientId: string; walletAdapterNetwork: | WalletAdapterNetwork.Mainnet | WalletAdapterNetwork.Devnet; tipLinkAutoConnect?: boolean; theme?: string; hideDraggableWidget?: boolean; autoConnect?: boolean; hideWalletOnboard?: boolean; }): string { const tipLinkUrl = getTipLinkUrl(buildEnv); const tipLinkIframeUrl = new URL(iframePath, tipLinkUrl); tipLinkIframeUrl.searchParams.append("c", clientId); tipLinkIframeUrl.searchParams.append( "ref", encodeURI(window.location.origin) ); tipLinkIframeUrl.searchParams.append("v", NPM_VERSION); if (autoConnect) { tipLinkIframeUrl.searchParams.append("autoConnect", "true"); } if (tipLinkAutoConnect) { tipLinkIframeUrl.searchParams.append("tipLinkAutoConnect", "true"); } if (theme) { tipLinkIframeUrl.searchParams.append("theme", theme); } if (hideDraggableWidget) { tipLinkIframeUrl.searchParams.append("hideWidget", "true"); } if (hideWalletOnboard) { tipLinkIframeUrl.searchParams.append("hideWalletOnboard", "true"); } if (walletAdapterNetwork === WalletAdapterNetwork.Devnet) { tipLinkIframeUrl.searchParams.append("devnet", "true"); } return tipLinkIframeUrl.href; } export const TIPLINK_ADAPTER_KEY = "TipLinkAdapter"; export const TIPLINK_EMBED_KEY = "TipLinkEmbed"; export enum TipLinkInstanceKey { ADAPTER = TIPLINK_ADAPTER_KEY, EMBED = TIPLINK_EMBED_KEY, } const TIPLINK_INSTANCES: Record< string, TipLinkWalletAdapter | TipLinkEmbed | undefined > = { [TIPLINK_ADAPTER_KEY]: undefined, [TIPLINK_EMBED_KEY]: undefined, }; export function removePreviousWindowRef(key: TipLinkInstanceKey) { if (!(key in TIPLINK_INSTANCES)) return; TIPLINK_INSTANCES[key] = undefined; } export function checkAndRemovePreviousTipLinkInstance(key: TipLinkInstanceKey) { try { // disconnect previous instance (adapter or embed class) if ( key === TipLinkInstanceKey.ADAPTER && TIPLINK_INSTANCES[key] instanceof TipLinkWalletAdapter ) { (TIPLINK_INSTANCES[key] as TipLinkWalletAdapter).disconnect(); } else if ( key === TipLinkInstanceKey.EMBED && TIPLINK_INSTANCES[key] instanceof TipLinkEmbed ) { (TIPLINK_INSTANCES[key] as TipLinkEmbed).clearElements(); } // remove reference of previous instance } catch (err) { console.error(`Error removing previous ${key} instance: `, err); } finally { // detach ref even if error occurs removePreviousWindowRef(key); } } export function checkAndAttachTipLinkInstance( tipLinkInstance: TipLinkWalletAdapter | TipLinkEmbed ) { // determine key from instance passed const key = tipLinkInstance instanceof TipLinkWalletAdapter ? TIPLINK_ADAPTER_KEY : tipLinkInstance instanceof TipLinkEmbed ? TIPLINK_EMBED_KEY : ""; if (!key) return; if (key in TIPLINK_INSTANCES && TIPLINK_INSTANCES[key]) { checkAndRemovePreviousTipLinkInstance(key as TipLinkInstanceKey); } TIPLINK_INSTANCES[key] = tipLinkInstance; } export function isElement(element: unknown) { return element instanceof Element || element instanceof Document; }