@hashgraphonline/hashinal-wc 2.0.62 → 2.0.64
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/es/index.js +38 -1
- package/dist/es/index.js.map +1 -1
- package/dist/umd/hashinal-wc.umd.js +13868 -0
- package/dist/umd/hashinal-wc.umd.js.map +1 -0
- package/dist/umd/index.d.ts +161 -0
- package/dist/umd/logger.d.ts +10 -0
- package/dist/umd/sign/index.d.ts +1 -0
- package/dist/umd/types.d.ts +254 -0
- package/dist/umd/utils/retry.d.ts +1 -0
- package/package.json +1 -1
package/dist/es/index.js
CHANGED
|
@@ -68,7 +68,15 @@ async function openHashPackOnMobile(wcUri) {
|
|
|
68
68
|
} catch {
|
|
69
69
|
}
|
|
70
70
|
const deepLink = getHashPackDeepLink(wcUri);
|
|
71
|
-
|
|
71
|
+
const anchor = document.createElement("a");
|
|
72
|
+
anchor.href = deepLink;
|
|
73
|
+
anchor.style.display = "none";
|
|
74
|
+
anchor.setAttribute("target", "_blank");
|
|
75
|
+
anchor.setAttribute("rel", "noopener noreferrer");
|
|
76
|
+
document.body.appendChild(anchor);
|
|
77
|
+
anchor.click();
|
|
78
|
+
document.body.removeChild(anchor);
|
|
79
|
+
await new Promise((resolve) => setTimeout(resolve, 500));
|
|
72
80
|
}
|
|
73
81
|
let windowOpenPatched = false;
|
|
74
82
|
let originalWindowOpen = null;
|
|
@@ -85,6 +93,35 @@ function patchWindowOpenForMobileWalletLinks() {
|
|
|
85
93
|
sessionStorage.setItem(WALLET_RETURN_URL_KEY, window.location.href);
|
|
86
94
|
} catch {
|
|
87
95
|
}
|
|
96
|
+
try {
|
|
97
|
+
const newWindow = originalWindowOpen(urlString, "_blank", "noopener,noreferrer");
|
|
98
|
+
if (newWindow) {
|
|
99
|
+
return newWindow;
|
|
100
|
+
}
|
|
101
|
+
} catch {
|
|
102
|
+
}
|
|
103
|
+
try {
|
|
104
|
+
const anchor = document.createElement("a");
|
|
105
|
+
anchor.href = urlString;
|
|
106
|
+
anchor.target = "_blank";
|
|
107
|
+
anchor.rel = "noopener noreferrer";
|
|
108
|
+
anchor.style.cssText = "position:fixed;top:-9999px;left:-9999px;";
|
|
109
|
+
document.body.appendChild(anchor);
|
|
110
|
+
const clickEvent = new MouseEvent("click", {
|
|
111
|
+
view: window,
|
|
112
|
+
bubbles: true,
|
|
113
|
+
cancelable: true
|
|
114
|
+
});
|
|
115
|
+
anchor.dispatchEvent(clickEvent);
|
|
116
|
+
setTimeout(() => {
|
|
117
|
+
try {
|
|
118
|
+
document.body.removeChild(anchor);
|
|
119
|
+
} catch {
|
|
120
|
+
}
|
|
121
|
+
}, 100);
|
|
122
|
+
return null;
|
|
123
|
+
} catch {
|
|
124
|
+
}
|
|
88
125
|
window.location.href = urlString;
|
|
89
126
|
return null;
|
|
90
127
|
}
|
package/dist/es/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../../src/index.ts"],"sourcesContent":["function ensureGlobalHTMLElement() {\n if (typeof globalThis === 'undefined') {\n return;\n }\n if (typeof (globalThis as any).HTMLElement === 'undefined') {\n (globalThis as any).HTMLElement = class {};\n }\n}\n\nensureGlobalHTMLElement();\n\nimport { Buffer } from 'buffer';\nimport { SessionTypes, SignClientTypes } from '@walletconnect/types';\nimport {\n Transaction,\n TransferTransaction,\n TopicMessageSubmitTransaction,\n ContractExecuteTransaction,\n Hbar,\n TransactionId,\n AccountId,\n TopicId,\n ContractId,\n LedgerId,\n TokenCreateTransaction,\n TokenType,\n TokenSupplyType,\n TokenMintTransaction,\n TopicCreateTransaction,\n TransactionReceipt,\n ContractFunctionParameters,\n PrivateKey,\n AccountCreateTransaction,\n TokenAssociateTransaction,\n TokenDissociateTransaction,\n AccountUpdateTransaction,\n AccountAllowanceApproveTransaction,\n TokenId,\n} from '@hashgraph/sdk';\nimport * as HashgraphSDK from '@hashgraph/sdk';\nimport { createAppKit } from '@reown/appkit';\nimport type { AppKit } from '@reown/appkit';\nimport {\n HederaSessionEvent,\n HederaJsonRpcMethod,\n DAppConnector,\n HederaAdapter,\n HederaChainDefinition,\n HederaChainId,\n hederaNamespace,\n HederaProvider,\n SignMessageResult,\n extensionOpen,\n ExtensionData,\n} from '@hashgraph/hedera-wallet-connect';\nimport {\n Message,\n FetchMessagesResult,\n TokenBalance,\n HederaAccountResponse,\n HederaTXResponse,\n HBarNFT,\n Nft,\n} from './types';\nimport { Logger } from './logger';\nimport { fetchWithRetry } from './utils/retry';\n\nconst HASH_PACK_WALLET_ID =\n 'a29498d225fa4b13468ff4d6cf4ae0ea4adcbd95f07ce8a843a1dee10b632f3f';\n\n/**\n * Well-known HashPack browser extension ID.\n * Used to trigger the extension popup for signing when the signer doesn't have an extensionId.\n */\nconst HASHPACK_EXTENSION_ID = 'gjagmgiddbbciopjhllkdnddhcglnemk';\n\n/**\n * HashPack deep link for mobile wallet connection\n * \n * IMPORTANT: HashPack only supports the universal link format (https://link.hashpack.app).\n * The hashpack:// custom scheme does not exist and will not work.\n */\nconst HASHPACK_DEEP_LINK = 'https://link.hashpack.app';\n\n/**\n * HashPack app store URLs for fallback when app is not installed\n */\nconst HASHPACK_STORE_URLS = {\n ios: 'https://apps.apple.com/app/hashpack/id1646514851',\n android: 'https://play.google.com/store/apps/details?id=app.hashpack.wallet',\n fallback: 'https://www.hashpack.app/',\n} as const;\n\n/**\n * Key for storing the return URL in sessionStorage.\n */\nconst WALLET_RETURN_URL_KEY = 'hashinal_wc_return_url';\n\n/**\n * Detect if current device is mobile\n */\nfunction isMobileDevice(): boolean {\n if (typeof window === 'undefined' || typeof navigator === 'undefined') {\n return false;\n }\n const userAgent = navigator.userAgent || navigator.vendor || (window as any).opera || '';\n return /android|webos|iphone|ipad|ipod|blackberry|iemobile|opera mini/i.test(userAgent.toLowerCase());\n}\n\n/**\n * Detect if device is iOS\n */\nfunction isIOSDevice(): boolean {\n if (typeof navigator === 'undefined') return false;\n return /iphone|ipad|ipod/i.test(navigator.userAgent.toLowerCase());\n}\n\n/**\n * Detect if device is Android\n */\nfunction isAndroidDevice(): boolean {\n if (typeof navigator === 'undefined') return false;\n return /android/i.test(navigator.userAgent.toLowerCase());\n}\n\n/**\n * Get the HashPack deep link for WalletConnect connections.\n * Uses the universal link format (https://link.hashpack.app) which is the only\n * supported deep link format for HashPack.\n */\nfunction getHashPackDeepLink(wcUri?: string): string {\n if (wcUri) {\n return `${HASHPACK_DEEP_LINK}/wc?uri=${encodeURIComponent(wcUri)}`;\n }\n \n return `${HASHPACK_DEEP_LINK}/wc`;\n}\n\n/**\n * Get the appropriate app store URL for the current platform\n */\nfunction getHashPackStoreUrl(): string {\n if (isIOSDevice()) return HASHPACK_STORE_URLS.ios;\n if (isAndroidDevice()) return HASHPACK_STORE_URLS.android;\n return HASHPACK_STORE_URLS.fallback;\n}\n\n/**\n * Patches all signers in the DAppConnector to have the HashPack extensionId set.\n * \n * This ensures that when DAppSigner.request() is called, it will automatically\n * trigger extensionOpen() to open the HashPack browser extension popup.\n * \n * The extensionId property is readonly in TypeScript but can be assigned at runtime\n * since JavaScript doesn't enforce readonly constraints.\n * \n * @param dAppConnector - The DAppConnector instance with signers to patch\n * @param extensionId - The extension ID to set (defaults to HashPack)\n */\nfunction patchSignersWithExtensionId(\n dAppConnector: DAppConnector | null,\n extensionId: string = HASHPACK_EXTENSION_ID\n): void {\n if (!dAppConnector?.signers?.length) return;\n if (isMobileDevice()) return;\n \n for (const signer of dAppConnector.signers) {\n if (!signer.extensionId) {\n // TypeScript says extensionId is readonly, but JavaScript allows assignment\n (signer as any).extensionId = extensionId;\n }\n }\n}\n\n/**\n * Open HashPack app on mobile device.\n * Used primarily for sign requests after a connection is already established.\n * \n * Uses a hidden anchor element to trigger the deep link without navigating\n * away from the current page. This ensures users can return to the dApp\n * after signing in the wallet.\n * \n * @param wcUri - Optional WalletConnect URI to pass to HashPack\n */\nasync function openHashPackOnMobile(wcUri?: string): Promise<void> {\n if (typeof window === 'undefined' || typeof document === 'undefined') return;\n \n try {\n sessionStorage.setItem(WALLET_RETURN_URL_KEY, window.location.href);\n } catch {\n /* sessionStorage not available */\n }\n\n const deepLink = getHashPackDeepLink(wcUri);\n \n window.location.href = deepLink;\n}\n\n/**\n * Flag to track if window.open has been patched for mobile wallet deep links.\n * We only want to patch once per page load.\n */\nlet windowOpenPatched = false;\n\n/**\n * Original window.open reference, stored before patching.\n */\nlet originalWindowOpen: typeof window.open | null = null;\n\n/**\n * Patch window.open to prevent mobile wallet deep links from navigating away\n * from the current page.\n * \n * On mobile browsers, opening wallet deep links typically navigates the current\n * page away. This patch intercepts those calls and:\n * \n * 1. Saves the current URL to sessionStorage before any navigation\n * 2. Attempts to open the deep link in a way that preserves the current page\n * 3. Falls back to direct navigation if needed, but with saved state for recovery\n * \n * The dApp should check for the return URL on page load and restore if needed.\n */\nfunction patchWindowOpenForMobileWalletLinks(): void {\n if (windowOpenPatched) return;\n if (typeof window === 'undefined') return;\n \n try {\n originalWindowOpen = window.open.bind(window);\n \n window.open = function(\n url?: string | URL,\n target?: string,\n features?: string\n ): WindowProxy | null {\n const urlString = url?.toString() || '';\n const isWalletDeepLink = urlString.includes('link.hashpack.app') || \n urlString.includes('wallet.hashpack.app');\n \n if (isMobileDevice() && isWalletDeepLink && (target === '_self' || target === '_top')) {\n try {\n sessionStorage.setItem(WALLET_RETURN_URL_KEY, window.location.href);\n } catch {\n /* sessionStorage not available */\n }\n \n window.location.href = urlString;\n return null;\n }\n \n return originalWindowOpen!(url, target, features);\n };\n \n windowOpenPatched = true;\n } catch {\n /* Patch failed silently - fallback to default behavior */\n }\n}\n\n/**\n * Check if there's a saved return URL from a wallet connection attempt.\n * If found, returns the URL and clears it from storage.\n * \n * dApps should call this on page load and redirect if a URL is returned.\n */\nfunction checkWalletReturnUrl(): string | null {\n if (typeof window === 'undefined') return null;\n \n try {\n const returnUrl = sessionStorage.getItem(WALLET_RETURN_URL_KEY);\n if (returnUrl) {\n sessionStorage.removeItem(WALLET_RETURN_URL_KEY);\n return returnUrl;\n }\n } catch {\n /* sessionStorage not available */\n }\n \n return null;\n}\n\n/**\n * Remove the window.open patch (for cleanup if needed)\n */\nfunction unpatchWindowOpen(): void {\n if (!windowOpenPatched || !originalWindowOpen) return;\n if (typeof window === 'undefined') return;\n \n try {\n window.open = originalWindowOpen;\n windowOpenPatched = false;\n originalWindowOpen = null;\n } catch {\n /* Unpatch failed silently */\n }\n}\n\nclass HashinalsWalletConnectSDK {\n private static instance: HashinalsWalletConnectSDK;\n private static dAppConnectorInstance: DAppConnector;\n private static proxyInstance: HashinalsWalletConnectSDK | null = null;\n private logger: Logger;\n private network: LedgerId;\n private reownAppKit: AppKit | null = null;\n private reownAppKitKey: string | null = null;\n private extensionCheckInterval: NodeJS.Timeout | null = null;\n private hasCalledExtensionCallback: boolean = false;\n private useAppKit: boolean = false;\n\n public get dAppConnector(): DAppConnector {\n return HashinalsWalletConnectSDK.dAppConnectorInstance;\n }\n\n constructor(logger?: Logger, network?: LedgerId) {\n this.logger = logger || new Logger();\n this.network = network || LedgerId.MAINNET;\n }\n\n public static getInstance(\n logger?: Logger,\n network?: LedgerId\n ): HashinalsWalletConnectSDK {\n let instance = HashinalsWalletConnectSDK?.instance;\n if (!instance) {\n HashinalsWalletConnectSDK.instance = new HashinalsWalletConnectSDK(\n logger,\n network\n );\n instance = HashinalsWalletConnectSDK.instance;\n HashinalsWalletConnectSDK.proxyInstance = null;\n }\n if (network) {\n instance.setNetwork(network);\n }\n if (!HashinalsWalletConnectSDK.proxyInstance) {\n HashinalsWalletConnectSDK.proxyInstance =\n new Proxy(instance, {\n get(target, prop, receiver) {\n const value = Reflect.get(target, prop, receiver);\n if (typeof value === 'function') {\n return value.bind(target);\n }\n return value;\n },\n }) as HashinalsWalletConnectSDK;\n }\n return HashinalsWalletConnectSDK.proxyInstance;\n }\n\n public setLogger(logger: Logger): void {\n this.logger = logger;\n }\n\n public setNetwork(network: LedgerId): void {\n this.network = network;\n }\n\n public getNetwork(): LedgerId {\n return this.network;\n }\n\n public setReownAppKit(appKit: AppKit | null): void {\n this.reownAppKit = appKit;\n }\n\n private async ensureReownAppKit(\n projectId: string,\n metadata: SignClientTypes.Metadata,\n network: LedgerId\n ): Promise<void> {\n if (typeof window === 'undefined') {\n return;\n }\n\n const key = `${projectId}:${network.toString()}`;\n if (this.reownAppKit && this.reownAppKitKey === key) {\n return;\n }\n\n try {\n const isTestnet = network.toString() === 'testnet';\n const defaultNetwork = isTestnet\n ? HederaChainDefinition.Native.Testnet\n : HederaChainDefinition.Native.Mainnet;\n\n /**\n * Create two adapters following hedera-app pattern:\n * 1. Native Hedera adapter (hederaNamespace)\n * 2. EIP155 adapter for EVM compatibility\n */\n const nativeHederaAdapter = new HederaAdapter({\n projectId,\n networks: isTestnet\n ? [HederaChainDefinition.Native.Testnet, HederaChainDefinition.Native.Mainnet]\n : [HederaChainDefinition.Native.Mainnet, HederaChainDefinition.Native.Testnet],\n namespace: hederaNamespace,\n });\n\n const eip155HederaAdapter = new HederaAdapter({\n projectId,\n networks: isTestnet\n ? [HederaChainDefinition.EVM.Testnet, HederaChainDefinition.EVM.Mainnet]\n : [HederaChainDefinition.EVM.Mainnet, HederaChainDefinition.EVM.Testnet],\n namespace: 'eip155',\n });\n\n /**\n * Create universal provider with optionalNamespaces\n * Following hedera-app pattern - HashPack only uses the first chain in the list\n */\n const providerOpts = {\n projectId,\n metadata,\n optionalNamespaces: {\n eip155: {\n methods: [\n 'eth_sendTransaction',\n 'eth_signTransaction',\n 'eth_sign',\n 'personal_sign',\n 'eth_signTypedData',\n 'eth_signTypedData_v4',\n 'eth_accounts',\n 'eth_chainId',\n ],\n chains: isTestnet\n ? ['eip155:296', 'eip155:295']\n : ['eip155:295', 'eip155:296'],\n events: ['chainChanged', 'accountsChanged'],\n rpcMap: {\n 'eip155:296': 'https://testnet.hashio.io/api',\n 'eip155:295': 'https://mainnet.hashio.io/api',\n },\n },\n hedera: {\n methods: [\n 'hedera_getNodeAddresses',\n 'hedera_executeTransaction',\n 'hedera_signMessage',\n 'hedera_signAndExecuteQuery',\n 'hedera_signAndExecuteTransaction',\n 'hedera_signTransaction',\n ],\n chains: isTestnet\n ? ['hedera:testnet', 'hedera:mainnet']\n : ['hedera:mainnet', 'hedera:testnet'],\n events: ['chainChanged', 'accountsChanged'],\n },\n },\n };\n\n const universalProvider = await HederaProvider.init(providerOpts);\n\n this.reownAppKit = createAppKit({\n adapters: [nativeHederaAdapter, eip155HederaAdapter],\n universalProvider,\n projectId,\n metadata,\n networks: [\n HederaChainDefinition.Native.Mainnet,\n HederaChainDefinition.Native.Testnet,\n HederaChainDefinition.EVM.Mainnet,\n HederaChainDefinition.EVM.Testnet,\n ],\n defaultNetwork,\n enableWalletGuide: true,\n enableWallets: true,\n enableReconnect: true,\n enableWalletConnect: false,\n allWallets: 'HIDE',\n featuredWalletIds: [HASH_PACK_WALLET_ID],\n features: {\n analytics: true,\n socials: false,\n swaps: false,\n onramp: false,\n email: false,\n },\n themeVariables: {\n '--w3m-accent': '#5599fe',\n },\n chainImages: {\n 'hedera:testnet': 'https://arweave.net/mBqmJSvl4wGWbUv3XbMHmwpjlVzO2zZCY9xPQWMwBxw',\n 'hedera:mainnet': 'https://arweave.net/mBqmJSvl4wGWbUv3XbMHmwpjlVzO2zZCY9xPQWMwBxw',\n 'eip155:296': 'https://arweave.net/mBqmJSvl4wGWbUv3XbMHmwpjlVzO2zZCY9xPQWMwBxw',\n 'eip155:295': 'https://arweave.net/mBqmJSvl4wGWbUv3XbMHmwpjlVzO2zZCY9xPQWMwBxw',\n },\n termsConditionsUrl: metadata.url ? `${metadata.url}/legal/terms` : undefined,\n privacyPolicyUrl: metadata.url ? `${metadata.url}/legal/privacy` : undefined,\n }) as AppKit;\n this.reownAppKitKey = key;\n \n patchWindowOpenForMobileWalletLinks();\n } catch (e) {\n this.logger.warn('Failed to initialize Reown AppKit', e);\n this.reownAppKit = null;\n this.reownAppKitKey = null;\n }\n }\n\n public setLogLevel(level: 'error' | 'warn' | 'info' | 'debug'): void {\n if (this.logger instanceof Logger) {\n this.logger.setLogLevel(level);\n }\n }\n\n public async init(\n projectId: string,\n metadata: SignClientTypes.Metadata,\n network?: LedgerId,\n onSessionIframeCreated?: (session: SessionTypes.Struct) => void,\n options?: { useAppKit?: boolean }\n ): Promise<DAppConnector> {\n patchWindowOpenForMobileWalletLinks();\n \n this.useAppKit = options?.useAppKit ?? false;\n \n const chosenNetwork = network || this.network;\n const isMainnet = chosenNetwork.toString() === 'mainnet';\n\n const existingConnector = HashinalsWalletConnectSDK.dAppConnectorInstance;\n if (existingConnector?.walletConnectClient) {\n return existingConnector;\n }\n\n const dAppConnector = new DAppConnector(\n metadata,\n chosenNetwork,\n projectId,\n Object.values(HederaJsonRpcMethod),\n [HederaSessionEvent.ChainChanged, HederaSessionEvent.AccountsChanged],\n [isMainnet ? HederaChainId.Mainnet : HederaChainId.Testnet],\n 'debug'\n );\n\n await dAppConnector.init({\n logger: 'error',\n });\n\n HashinalsWalletConnectSDK.dAppConnectorInstance = dAppConnector;\n\n if (this.useAppKit) {\n await this.ensureReownAppKit(projectId, metadata, chosenNetwork);\n }\n\n HashinalsWalletConnectSDK.dAppConnectorInstance.onSessionIframeCreated = (\n session\n ) => {\n this.logger.info('new session from from iframe', session);\n this.handleNewSession(session);\n patchSignersWithExtensionId(HashinalsWalletConnectSDK.dAppConnectorInstance);\n if (onSessionIframeCreated) {\n onSessionIframeCreated(session);\n }\n };\n\n this.logger.info(\n `Hedera Wallet Connect SDK initialized on ${chosenNetwork}`\n );\n \n patchSignersWithExtensionId(HashinalsWalletConnectSDK.dAppConnectorInstance);\n \n return HashinalsWalletConnectSDK.dAppConnectorInstance;\n }\n\n public async connect(options?: {\n pairingTopic?: string;\n onUri?: (uri: string) => void;\n }): Promise<SessionTypes.Struct> {\n this.ensureInitialized();\n const pairingTopic = options?.pairingTopic;\n \n // If AppKit is enabled and available, use it (for MetaMask/EVM wallet support)\n const appKit = this.useAppKit ? this.reownAppKit : null;\n if (appKit) {\n const session = await this.connectUsingReownAppKit(\n appKit,\n pairingTopic,\n options?.onUri\n );\n this.handleNewSession(session);\n patchSignersWithExtensionId(this.dAppConnector);\n return session;\n }\n\n // Simple HashPack-only flow (default)\n const availableExtension = this.getAvailableDesktopExtension();\n \n // Desktop with extension: connect directly\n if (availableExtension?.id) {\n this.logger.info('Desktop extension available, connecting directly...');\n try {\n const session = await this.dAppConnector.connectExtension(\n availableExtension.id,\n pairingTopic\n );\n this.handleNewSession(session);\n patchSignersWithExtensionId(this.dAppConnector);\n return session;\n } catch (e) {\n this.logger.warn('Direct extension connection failed, falling back to modal', e);\n }\n }\n\n // Mobile: use deep link to HashPack\n if (isMobileDevice()) {\n this.logger.info('Mobile device detected, using HashPack deep link...');\n const session = await this.dAppConnector.connect(\n (uri) => {\n openHashPackOnMobile(uri);\n },\n pairingTopic,\n undefined\n );\n this.handleNewSession(session);\n patchSignersWithExtensionId(this.dAppConnector);\n return session;\n }\n\n // Desktop without extension: use DAppConnector's built-in modal\n this.logger.info('Opening DAppConnector modal...');\n const session = await this.dAppConnector.openModal(pairingTopic);\n this.handleNewSession(session);\n patchSignersWithExtensionId(this.dAppConnector);\n return session;\n }\n\n private async connectUsingReownAppKit(\n appKit: AppKit,\n pairingTopic?: string,\n onUri?: (uri: string) => void\n ): Promise<SessionTypes.Struct> {\n this.ensureInitialized();\n if (!appKit) {\n throw new Error('AppKit instance is required.');\n }\n\n const availableExtension = this.getAvailableDesktopExtension();\n\n // Desktop with extension available: connect directly without modal\n if (availableExtension?.id) {\n this.logger.info('Desktop extension available, connecting directly...');\n try {\n const session = await this.dAppConnector.connectExtension(\n availableExtension.id,\n pairingTopic\n );\n return session;\n } catch (e) {\n this.logger.warn(\n 'Direct extension connection failed, falling back to AppKit modal',\n e\n );\n // Fall through to AppKit modal\n }\n }\n\n // Mobile: deep link to HashPack directly\n if (isMobileDevice()) {\n this.logger.info('Mobile device detected, using HashPack deep link...');\n return await this.dAppConnector.connect(\n (uri) => {\n openHashPackOnMobile(uri);\n },\n pairingTopic,\n undefined\n );\n }\n\n /**\n * Desktop without extension: Use AppKit's native connect flow\n * Following hedera-app pattern - let AppKit handle the entire UX\n */\n this.logger.info('Desktop without extension, opening AppKit Connect modal...');\n\n // Open AppKit's native connect modal with hedera namespace\n // This provides a clean UX with wallet selection, QR code, etc.\n await appKit.open({ view: 'Connect' });\n\n // Wait for the connection to be established\n // AppKit will handle showing QR codes, wallet selection, etc.\n return new Promise<SessionTypes.Struct>((resolve, reject) => {\n let resolved = false;\n const checkInterval = setInterval(() => {\n // Check if we have a new session\n const signers = this.dAppConnector?.signers || [];\n if (signers.length > 0) {\n const session = this.dAppConnector?.walletConnectClient?.session?.getAll()?.[0];\n if (session && !resolved) {\n resolved = true;\n clearInterval(checkInterval);\n void appKit.close().catch(() => {});\n resolve(session);\n }\n }\n }, 500);\n\n // Timeout after 5 minutes\n setTimeout(() => {\n if (!resolved) {\n clearInterval(checkInterval);\n void appKit.close().catch(() => {});\n reject(new Error('Connection timeout - no wallet connected'));\n }\n }, 5 * 60 * 1000);\n\n // Also listen for AppKit state changes\n const unsubscribe = appKit.subscribeState?.((state: { open?: boolean }) => {\n if (state.open === false && !resolved) {\n // Modal was closed without connecting\n clearInterval(checkInterval);\n unsubscribe?.();\n reject(new Error('Connection cancelled - modal closed'));\n }\n });\n });\n }\n\n public async disconnect(): Promise<boolean> {\n try {\n this.ensureInitialized();\n const accountInfo = this.getAccountInfo();\n const accountId = accountInfo?.accountId;\n const network = accountInfo?.network;\n const signer = this?.dAppConnector?.signers.find(\n (signer_) => signer_.getAccountId().toString() === accountId\n );\n await this.dAppConnector?.disconnect(signer?.topic);\n this.logger.info(`Disconnected from ${accountId} on ${network}`);\n return true;\n } catch (e) {\n this.logger.error('Failed to disconnect', e);\n return false;\n }\n }\n\n public async disconnectAll(): Promise<boolean> {\n try {\n this.ensureInitialized();\n await this.dAppConnector?.disconnectAll();\n this.logger.info(`Disconnected from all wallets`);\n return true;\n } catch (e) {\n this.logger.error('Failed to disconnect', e);\n return false;\n }\n }\n\n /**\n * Triggers the browser extension popup for signing on desktop.\n * This is needed when the signer doesn't have an extensionId set\n * (e.g., when connecting via the Reown AppKit modal).\n */\n private triggerExtensionPopupIfNeeded(): void {\n if (isMobileDevice()) {\n return;\n }\n\n const availableExtension = this.getAvailableDesktopExtension();\n\n if (availableExtension) {\n this.logger.debug(\n 'Triggering extension popup for signing',\n availableExtension.id\n );\n extensionOpen(availableExtension.id);\n }\n }\n\n /**\n * Gets the available desktop browser extension (e.g., HashPack).\n * Returns undefined if no extension is available or on mobile devices.\n */\n private getAvailableDesktopExtension(): ExtensionData | undefined {\n if (isMobileDevice()) {\n return undefined;\n }\n\n const extensions = this.dAppConnector?.extensions || [];\n return extensions.find((ext) => ext.available && !ext.availableInIframe);\n }\n\n public async executeTransaction(\n tx: Transaction,\n disableSigner: boolean = false\n ): Promise<TransactionReceipt> {\n this.ensureInitialized();\n const accountInfo = this.getAccountInfo();\n const accountId = accountInfo?.accountId;\n const signer = this.dAppConnector.signers.find(\n (signer_) => signer_.getAccountId().toString() === accountId\n );\n\n if (!signer) {\n throw new Error('No signer available. Please ensure wallet is connected.');\n }\n\n // Trigger wallet prompt before signing\n if (isMobileDevice()) {\n // On mobile, open HashPack app for transaction signing\n this.logger.info('Mobile device detected, opening HashPack app for transaction signing...');\n await openHashPackOnMobile();\n } else if (!signer.extensionId) {\n // On desktop, trigger extension popup if the signer doesn't have extensionId set\n // This happens when connecting via the Reown AppKit modal\n this.triggerExtensionPopupIfNeeded();\n }\n\n try {\n if (!disableSigner) {\n const signedTx = await tx.freezeWithSigner(signer);\n const executedTx = await signedTx.executeWithSigner(signer);\n return await executedTx.getReceiptWithSigner(signer);\n }\n const executedTx = await tx.executeWithSigner(signer);\n return await executedTx.getReceiptWithSigner(signer);\n } catch (e) {\n const message = (e as Error).message ?? '';\n if (message.toLowerCase().includes('nodeaccountid')) {\n throw new Error(\n 'Transaction execution failed because nodeAccountId is not set. Set node account IDs on the transaction before calling executeTransaction.'\n );\n }\n throw e;\n }\n }\n\n public async executeTransactionWithErrorHandling(\n tx: Transaction,\n disableSigner: boolean\n ): Promise<{ result?: TransactionReceipt; error?: string }> {\n try {\n const result = await this.executeTransaction(tx, disableSigner);\n return {\n result,\n error: undefined,\n };\n } catch (e) {\n const error = e as Error;\n const message = error.message?.toLowerCase();\n this.logger.error('Failed to execute transaction', e);\n this.logger.error('Failure reason for transaction is', message);\n if (message.includes('insufficient payer balance')) {\n return {\n result: undefined,\n error: 'Insufficient balance to complete the transaction.',\n };\n } else if (message.includes('reject')) {\n return {\n result: undefined,\n error: 'You rejected the transaction',\n };\n } else if (message.includes('invalid signature')) {\n return {\n result: undefined,\n error: 'Invalid signature. Please check your account and try again.',\n };\n } else if (message.includes('transaction expired')) {\n return {\n result: undefined,\n error: 'Transaction expired. Please try again.',\n };\n } else if (message.includes('account not found')) {\n return {\n result: undefined,\n error:\n 'Account not found. Please check the account ID and try again.',\n };\n } else if (message.includes('unauthorized')) {\n return {\n result: undefined,\n error:\n 'Unauthorized. You may not have the necessary permissions for this action.',\n };\n } else if (message.includes('busy')) {\n return {\n result: undefined,\n error: 'The network is busy. Please try again later.',\n };\n } else if (message.includes('invalid transaction')) {\n return {\n result: undefined,\n error: 'Invalid transaction. Please check your inputs and try again.',\n };\n }\n }\n }\n\n public async submitMessageToTopic(\n topicId: string,\n message: string,\n submitKey?: PrivateKey\n ): Promise<TransactionReceipt> {\n this.ensureInitialized();\n\n let transaction = new TopicMessageSubmitTransaction()\n .setTopicId(TopicId.fromString(topicId))\n .setMessage(message);\n\n if (submitKey) {\n transaction = await transaction.sign(submitKey);\n }\n\n return this.executeTransaction(transaction);\n }\n\n public async transferHbar(\n fromAccountId: string,\n toAccountId: string,\n amount: number\n ): Promise<TransactionReceipt> {\n this.ensureInitialized();\n\n const transaction = new TransferTransaction()\n .setTransactionId(TransactionId.generate(fromAccountId))\n .addHbarTransfer(AccountId.fromString(fromAccountId), new Hbar(-amount))\n .addHbarTransfer(AccountId.fromString(toAccountId), new Hbar(amount));\n\n return this.executeTransaction(transaction);\n }\n\n async executeSmartContract(\n contractId: string,\n functionName: string,\n parameters: ContractFunctionParameters,\n gas: number = 100000\n ): Promise<TransactionReceipt> {\n this.ensureInitialized();\n\n const transaction = new ContractExecuteTransaction()\n .setContractId(ContractId.fromString(contractId))\n .setGas(gas)\n .setFunction(functionName, parameters);\n\n return this.executeTransaction(transaction);\n }\n\n private handleNewSession(session: SessionTypes.Struct) {\n const sessionAccount = session.namespaces?.hedera?.accounts?.[0];\n const sessionParts = sessionAccount?.split(':');\n const accountId = sessionParts.pop();\n const network = sessionParts.pop();\n this.logger.info('sessionAccount is', accountId, network);\n if (!accountId) {\n this.logger.error('No account id found in the session');\n return;\n } else {\n this.saveConnectionInfo(accountId, network);\n }\n }\n\n private getNetworkPrefix(): string {\n const accountInfo = this.getAccountInfo();\n const network = accountInfo?.network;\n\n if (!network) {\n this.logger.warn('Network is not set on SDK, defaulting.');\n\n const cachedNetwork = localStorage.getItem('connectedNetwork');\n\n if (cachedNetwork) {\n return cachedNetwork;\n }\n\n return 'mainnet-public';\n }\n\n if (network !== this.network) {\n this.logger.warn(\n 'Detected network mismatch, reverting to signer network',\n network\n );\n this.network = network;\n }\n\n return network.isMainnet() ? 'mainnet-public' : 'testnet';\n }\n\n public async requestAccount(account: string): Promise<HederaAccountResponse> {\n try {\n const networkPrefix = this.getNetworkPrefix();\n\n const url = `https://${networkPrefix}.mirrornode.hedera.com/api/v1/accounts/${account}`;\n const response = await fetchWithRetry()(url);\n if (!response.ok) {\n throw new Error(\n `Failed to make request to mirror node for account: ${response.status}`\n );\n }\n return await response.json();\n } catch (e) {\n this.logger.error('Failed to fetch account', e);\n throw e;\n }\n }\n\n public async getAccountBalance(): Promise<string> {\n this.ensureInitialized();\n const accountInfo = this.getAccountInfo();\n const account = accountInfo?.accountId;\n\n if (!account) {\n return null;\n }\n\n const accountResponse = await this.requestAccount(account);\n if (!accountResponse) {\n throw new Error(\n 'Failed to fetch account. Try again or check if the Account ID is valid.'\n );\n }\n const balance = accountResponse.balance.balance / 10 ** 8;\n return Number(balance).toLocaleString('en-US');\n }\n\n public getAccountInfo(): {\n accountId: string;\n network: LedgerId;\n } {\n const { accountId: cachedAccountId } = this.loadConnectionInfo();\n if (!cachedAccountId) {\n return null;\n }\n const signers = this?.dAppConnector?.signers;\n\n if (!signers?.length) {\n return null;\n }\n\n const cachedSigner = this.dAppConnector.signers.find(\n (signer_) => signer_.getAccountId().toString() === cachedAccountId\n );\n if (!cachedSigner) {\n return null;\n }\n const accountId = cachedSigner?.getAccountId()?.toString();\n if (!accountId) {\n return null;\n }\n const network = cachedSigner.getLedgerId();\n return {\n accountId,\n network,\n };\n }\n\n public async createTopic(\n memo?: string,\n adminKey?: string,\n submitKey?: string\n ): Promise<string> {\n this.ensureInitialized();\n\n let transaction = new TopicCreateTransaction().setTopicMemo(memo || '');\n\n if (adminKey) {\n const adminWithPrivateKey = PrivateKey.fromString(adminKey);\n transaction.setAdminKey(adminWithPrivateKey.publicKey);\n transaction = await transaction.sign(adminWithPrivateKey);\n }\n\n if (submitKey) {\n transaction.setSubmitKey(PrivateKey.fromString(submitKey).publicKey);\n }\n\n const receipt = await this.executeTransaction(transaction);\n return receipt.topicId!.toString();\n }\n\n public async createToken(\n name: string,\n symbol: string,\n initialSupply: number,\n decimals: number,\n treasuryAccountId: string,\n adminKey: string,\n supplyKey: string\n ): Promise<string> {\n this.ensureInitialized();\n\n let transaction = new TokenCreateTransaction()\n .setTokenName(name)\n .setTokenSymbol(symbol)\n .setDecimals(decimals)\n .setInitialSupply(initialSupply)\n .setTreasuryAccountId(AccountId.fromString(treasuryAccountId))\n .setTokenType(TokenType.NonFungibleUnique)\n .setSupplyType(TokenSupplyType.Finite);\n\n if (supplyKey) {\n transaction = transaction.setSupplyKey(PrivateKey.fromString(supplyKey));\n }\n\n if (adminKey) {\n transaction = transaction.setAdminKey(PrivateKey.fromString(adminKey));\n transaction = await transaction.sign(PrivateKey.fromString(adminKey));\n }\n\n const receipt = await this.executeTransaction(transaction);\n return receipt.tokenId!.toString();\n }\n\n public async mintNFT(\n tokenId: string,\n metadata: string,\n supplyKey: PrivateKey\n ): Promise<TransactionReceipt> {\n this.ensureInitialized();\n\n let transaction = await new TokenMintTransaction()\n .setTokenId(tokenId)\n .setMetadata([Buffer.from(metadata, 'utf-8')])\n .sign(supplyKey);\n\n return this.executeTransaction(transaction);\n }\n\n public async getMessages(\n topicId: string,\n lastTimestamp?: number,\n disableTimestampFilter: boolean = false,\n network?: string\n ): Promise<FetchMessagesResult> {\n const networkPrefix = network || this.getNetworkPrefix();\n const baseUrl = `https://${networkPrefix}.mirrornode.hedera.com`;\n const timestampQuery =\n Number(lastTimestamp) > 0 && !disableTimestampFilter\n ? `×tamp=gt:${lastTimestamp}`\n : '';\n\n const url = `${baseUrl}/api/v1/topics/${topicId}/messages?limit=200${timestampQuery}`;\n\n try {\n const response = await fetchWithRetry()(url);\n if (!response.ok) {\n throw new Error(\n `Failed to make request to mirror node: ${response.status}`\n );\n }\n const data = await response.json();\n const messages = data?.messages || [];\n const nextLink = data?.links?.next;\n\n const collectedMessages: Message[] = messages.map((msg: any) => {\n const parsedMessage = JSON.parse(atob(msg.message));\n return {\n ...parsedMessage,\n payer: msg.payer_account_id,\n created: new Date(Number(msg.consensus_timestamp) * 1000),\n consensus_timestamp: msg.consensus_timestamp,\n sequence_number: msg.sequence_number,\n };\n });\n\n if (nextLink) {\n const nextResult = await this.getMessages(\n topicId,\n Number(\n collectedMessages[collectedMessages.length - 1]?.consensus_timestamp\n ),\n disableTimestampFilter\n );\n collectedMessages.push(...nextResult.messages);\n }\n\n return {\n messages: collectedMessages.sort(\n (a, b) => a.sequence_number - b.sequence_number\n ),\n error: '',\n };\n } catch (error) {\n this.logger.error('Error fetching topic data:', error);\n return {\n messages: [],\n error: (error as Error).toString(),\n };\n }\n }\n\n /**\n * Sign a message with the connected wallet.\n * On mobile devices, this will automatically open the HashPack app\n * to prompt the user to sign the message.\n * \n * @param message - The message to sign\n * @param options - Optional configuration for signing\n * @param options.openWalletOnMobile - Whether to open the wallet app on mobile (default: true)\n * @param options.onMobileRedirect - Callback before redirecting to wallet on mobile\n */\n public async signMessage(\n message: string,\n options?: {\n openWalletOnMobile?: boolean;\n onMobileRedirect?: () => void;\n }\n ) {\n const dAppConnector = this.dAppConnector;\n if (!dAppConnector) {\n throw new Error('No active connection or signer');\n }\n\n const accountInfo = this.getAccountInfo();\n const accountId = accountInfo?.accountId;\n\n if (!accountId) {\n throw new Error('No account connected. Please connect your wallet first.');\n }\n\n const params = {\n signerAccountId: `hedera:${this.network}:${accountId}`,\n message,\n };\n\n const shouldOpenWallet = options?.openWalletOnMobile !== false;\n if (shouldOpenWallet && isMobileDevice()) {\n this.logger.info('Mobile device detected, opening HashPack app for signing...');\n options?.onMobileRedirect?.();\n await openHashPackOnMobile();\n } else if (!isMobileDevice()) {\n // On desktop, trigger extension popup if needed\n this.triggerExtensionPopupIfNeeded();\n }\n\n try {\n const result = (await dAppConnector.signMessage(\n params\n )) as SignMessageResult;\n\n return { userSignature: (result as unknown as { signatureMap: string }).signatureMap };\n } catch (error) {\n if (isMobileDevice()) {\n const originalError = (error as Error).message || String(error);\n if (originalError.toLowerCase().includes('timeout') || \n originalError.toLowerCase().includes('reject') ||\n originalError.toLowerCase().includes('user')) {\n throw new Error(\n `Signing failed. Please make sure HashPack is open and try again. (${originalError})`\n );\n }\n }\n throw error;\n }\n }\n\n private saveConnectionInfo(\n accountId: string | undefined,\n connectedNetwork?: string | undefined\n ): void {\n if (!accountId) {\n localStorage.removeItem('connectedAccountId');\n localStorage.removeItem('connectedNetwork');\n } else {\n const cleanNetwork = connectedNetwork?.replace(/['\"]+/g, '');\n localStorage.setItem('connectedNetwork', cleanNetwork);\n localStorage.setItem('connectedAccountId', accountId);\n }\n }\n\n public loadConnectionInfo(): {\n accountId: string | null;\n network: string | null;\n } {\n return {\n accountId: localStorage.getItem('connectedAccountId'),\n network: localStorage.getItem('connectedNetwork'),\n };\n }\n\n public async connectWallet(\n PROJECT_ID: string,\n APP_METADATA: SignClientTypes.Metadata,\n network?: LedgerId,\n options?: { onUri?: (uri: string) => void; useAppKit?: boolean }\n ): Promise<{\n accountId: string;\n balance: string;\n session: SessionTypes.Struct;\n }> {\n try {\n await this.init(PROJECT_ID, APP_METADATA, network, undefined, { useAppKit: options?.useAppKit });\n const session = await this.connect({ onUri: options?.onUri });\n\n const accountInfo = this.getAccountInfo();\n const accountId = accountInfo?.accountId;\n const balance = await this.getAccountBalance();\n const networkPrefix = this.getNetworkPrefix();\n\n this.saveConnectionInfo(accountId, networkPrefix);\n return {\n accountId,\n balance,\n session,\n };\n } catch (error) {\n this.logger.error('Failed to connect wallet:', error);\n throw error;\n }\n }\n\n public async disconnectWallet(\n clearStorage: boolean = true\n ): Promise<boolean> {\n try {\n const success = await this.disconnect();\n\n if (success && clearStorage) {\n localStorage.clear();\n }\n\n this.saveConnectionInfo(undefined);\n return success;\n } catch (error) {\n this.logger.error('Failed to disconnect wallet:', error);\n return false;\n }\n }\n\n public async initAccount(\n PROJECT_ID: string,\n APP_METADATA: SignClientTypes.Metadata,\n networkOverride?: LedgerId,\n onSessionIframeCreated: (session: SessionTypes.Struct) => void = () => {},\n options?: { useAppKit?: boolean }\n ): Promise<{ accountId: string; balance: string } | null> {\n const { accountId: savedAccountId, network: savedNetwork } =\n this.loadConnectionInfo();\n\n if (savedAccountId && savedNetwork) {\n try {\n const defaultNetwork =\n savedNetwork === 'mainnet' ? LedgerId.MAINNET : LedgerId.TESTNET;\n const network = networkOverride || defaultNetwork;\n await this.init(\n PROJECT_ID,\n APP_METADATA,\n network,\n onSessionIframeCreated,\n { useAppKit: options?.useAppKit }\n );\n const balance = await this.getAccountBalance();\n return {\n accountId: savedAccountId,\n balance,\n };\n } catch (error) {\n this.logger.error('Failed to reconnect:', error);\n this.saveConnectionInfo(undefined, undefined);\n return null;\n }\n } else if (networkOverride) {\n try {\n this.logger.info(\n 'initializing normally through override.',\n networkOverride\n );\n await this.init(\n PROJECT_ID,\n APP_METADATA,\n networkOverride,\n onSessionIframeCreated,\n { useAppKit: options?.useAppKit }\n );\n this.logger.info('initialized', networkOverride);\n await this.connectViaDappBrowser();\n this.logger.info('connected via dapp browser');\n } catch (error) {\n this.logger.error('Failed to fallback connect:', error);\n this.saveConnectionInfo(undefined, undefined);\n return null;\n }\n }\n\n return null;\n }\n\n public subscribeToExtensions(callback: (extension: any) => void) {\n if (this.extensionCheckInterval) {\n clearInterval(this.extensionCheckInterval);\n }\n this.hasCalledExtensionCallback = false;\n\n this.extensionCheckInterval = setInterval(() => {\n const extensions = this.dAppConnector?.extensions || [];\n const availableExtension = extensions.find(\n (ext) => ext.availableInIframe\n );\n\n if (availableExtension && !this.hasCalledExtensionCallback) {\n this.hasCalledExtensionCallback = true;\n callback(availableExtension);\n if (this.extensionCheckInterval) {\n clearInterval(this.extensionCheckInterval);\n this.extensionCheckInterval = null;\n }\n }\n }, 1000);\n\n return () => {\n if (this.extensionCheckInterval) {\n clearInterval(this.extensionCheckInterval);\n this.extensionCheckInterval = null;\n }\n this.hasCalledExtensionCallback = false;\n };\n }\n\n public async connectViaDappBrowser() {\n const extensions = this.dAppConnector.extensions || [];\n const extension = extensions.find((ext) => {\n this.logger.info('Checking extension', ext);\n return ext.availableInIframe;\n });\n this.logger.info('extensions are', extensions, extension);\n\n if (extension) {\n await this.connectToExtension(extension);\n } else {\n // If no extension is immediately available, subscribe to changes\n this.subscribeToExtensions(async (newExtension) => {\n await this.connectToExtension(newExtension);\n });\n }\n }\n\n private async connectToExtension(extension: any) {\n this.logger.info('found extension, connecting to iframe.', extension);\n const session = await this.dAppConnector.connectExtension(extension.id);\n const onSessionIframeCreated = this.dAppConnector.onSessionIframeCreated;\n if (onSessionIframeCreated) {\n onSessionIframeCreated(session);\n }\n }\n\n private ensureInitialized(): void {\n if (!this.dAppConnector?.walletConnectClient) {\n throw new Error('WalletConnect is not initialized');\n }\n }\n\n static run(): void {\n try {\n if (typeof window !== 'undefined') {\n (window as any).HashinalsWalletConnectSDK =\n HashinalsWalletConnectSDK.getInstance();\n (window as any).HashgraphSDK = HashgraphSDK;\n }\n } catch (e) {\n console.error('[ERROR]: failed setting sdk on window');\n }\n }\n\n public async transferToken(\n tokenId: string,\n fromAccountId: string,\n toAccountId: string,\n amount: number\n ): Promise<TransactionReceipt> {\n this.ensureInitialized();\n\n const transaction = new TransferTransaction()\n .setTransactionId(TransactionId.generate(fromAccountId))\n .addTokenTransfer(\n TokenId.fromString(tokenId),\n AccountId.fromString(fromAccountId),\n -amount\n )\n .addTokenTransfer(\n TokenId.fromString(tokenId),\n AccountId.fromString(toAccountId),\n amount\n );\n\n return this.executeTransaction(transaction);\n }\n\n async createAccount(initialBalance: number): Promise<TransactionReceipt> {\n this.ensureInitialized();\n\n const transaction = new AccountCreateTransaction().setInitialBalance(\n new Hbar(initialBalance)\n );\n\n return this.executeTransaction(transaction);\n }\n\n public async associateTokenToAccount(\n accountId: string,\n tokenId: string\n ): Promise<TransactionReceipt> {\n this.ensureInitialized();\n\n const transaction = new TokenAssociateTransaction()\n .setAccountId(AccountId.fromString(accountId))\n .setTokenIds([TokenId.fromString(tokenId)]);\n\n return this.executeTransaction(transaction);\n }\n\n public async dissociateTokenFromAccount(\n accountId: string,\n tokenId: string\n ): Promise<TransactionReceipt> {\n this.ensureInitialized();\n\n const transaction = new TokenDissociateTransaction()\n .setAccountId(AccountId.fromString(accountId))\n .setTokenIds([TokenId.fromString(tokenId)]);\n\n return this.executeTransaction(transaction);\n }\n\n public async updateAccount(\n accountId: string,\n maxAutomaticTokenAssociations: number\n ): Promise<TransactionReceipt> {\n this.ensureInitialized();\n\n const transaction = new AccountUpdateTransaction()\n .setAccountId(AccountId.fromString(accountId))\n .setMaxAutomaticTokenAssociations(maxAutomaticTokenAssociations);\n\n return this.executeTransaction(transaction);\n }\n\n public async approveAllowance(\n spenderAccountId: string,\n tokenId: string,\n amount: number,\n ownerAccountId: string\n ): Promise<TransactionReceipt> {\n this.ensureInitialized();\n\n const transaction =\n new AccountAllowanceApproveTransaction().approveTokenAllowance(\n TokenId.fromString(tokenId),\n AccountId.fromString(ownerAccountId),\n AccountId.fromString(spenderAccountId),\n amount\n );\n\n return this.executeTransaction(transaction);\n }\n\n public async getAccountTokens(\n accountId: string\n ): Promise<{ tokens: TokenBalance[] }> {\n this.ensureInitialized();\n\n const networkPrefix = this.getNetworkPrefix();\n const baseUrl = `https://${networkPrefix}.mirrornode.hedera.com`;\n const url = `${baseUrl}/api/v1/accounts/${accountId}/tokens?limit=200`;\n\n try {\n const response = await fetchWithRetry()(url);\n if (!response.ok) {\n throw new Error(\n `Failed to make request to mirror node for account tokens: ${response.status}`\n );\n }\n const data = await response.json();\n\n const tokens: TokenBalance[] = [];\n\n for (const token of data.tokens) {\n if (token.token_id) {\n tokens.push({\n tokenId: token.token_id,\n balance: token.balance,\n decimals: token.decimals,\n formatted_balance: (\n token.balance /\n 10 ** token.decimals\n ).toLocaleString('en-US'),\n created_timestamp: new Date(Number(token.created_timestamp) * 1000),\n });\n }\n }\n let nextLink = data.links?.next;\n while (nextLink) {\n const nextUrl = `${baseUrl}${nextLink}`;\n const nextResponse = await fetchWithRetry()(nextUrl);\n if (!nextResponse.ok) {\n throw new Error(\n `Failed to make request to mirror node for account tokens: ${nextResponse.status}, page: ${nextUrl}`\n );\n }\n const nextData = await nextResponse.json();\n\n for (const token of nextData.tokens) {\n if (token.token_id) {\n tokens.push({\n tokenId: token.token_id,\n balance: token.balance,\n decimals: token.decimals,\n formatted_balance: (\n token.balance /\n 10 ** token.decimals\n ).toLocaleString('en-US'),\n created_timestamp: new Date(\n Number(token.created_timestamp) * 1000\n ),\n });\n }\n }\n\n nextLink = nextData.links?.next;\n }\n\n return { tokens };\n } catch (error) {\n this.logger.error('Error fetching account tokens:', error);\n throw error;\n }\n }\n\n public async getTransaction(\n transactionId: string\n ): Promise<HederaTXResponse | null> {\n try {\n const networkPrefix = this.getNetworkPrefix();\n const url = `https://${networkPrefix}.mirrornode.hedera.com/api/v1/transactions/${transactionId}`;\n\n this.logger.debug('Fetching transaction', url);\n const request = await fetchWithRetry()(url);\n\n if (!request.ok) {\n throw new Error(`Failed to fetch transaction: ${request.status}`);\n }\n\n return await request.json();\n } catch (e) {\n this.logger.error('Failed to get transaction', e);\n return null;\n }\n }\n\n public async getTransactionByTimestamp(\n timestamp: string\n ): Promise<HederaTXResponse | null> {\n try {\n const networkPrefix = this.getNetworkPrefix();\n const url = `https://${networkPrefix}.mirrornode.hedera.com/api/v1/transactions?timestamp=${timestamp}`;\n\n this.logger.debug('Fetching transaction by timestamp', url);\n const request = await fetchWithRetry()(url);\n\n if (!request.ok) {\n throw new Error(\n `Failed to fetch transaction by timestamp: ${request.status}`\n );\n }\n\n const response = (await request.json()) as HederaTXResponse;\n const transaction = response?.transactions?.[0];\n\n if (transaction) {\n return await this.getTransaction(transaction.transaction_id);\n }\n\n return null;\n } catch (e) {\n this.logger.error('Failed to get transaction by timestamp', e);\n return null;\n }\n }\n\n public async getAccountNFTs(\n accountId: string,\n tokenId?: string\n ): Promise<Nft[]> {\n try {\n const networkPrefix = this.getNetworkPrefix();\n const tokenQuery = tokenId ? `&token.id=${tokenId}` : '';\n const url = `https://${networkPrefix}.mirrornode.hedera.com/api/v1/accounts/${accountId}/nfts?limit=200${tokenQuery}`;\n\n const request = await fetchWithRetry()(url);\n if (!request.ok) {\n throw new Error(`Failed to fetch NFTs for account: ${request.status}`);\n }\n\n const response = (await request.json()) as HBarNFT;\n let nextLink: string | null = response?.links?.next || null;\n let nfts: Nft[] = (response.nfts || []) as Nft[];\n\n while (nextLink) {\n try {\n const nextRequest = await fetchWithRetry()(\n `https://${networkPrefix}.mirrornode.hedera.com${nextLink}`\n );\n\n if (!nextRequest.ok) {\n throw new Error(\n `Failed to fetch next page of NFTs: ${nextRequest.status}`\n );\n }\n\n const nextResponse = (await nextRequest.json()) as HBarNFT;\n const nextNfts = (nextResponse?.nfts || []) as Nft[];\n nfts = [...nfts, ...nextNfts];\n\n nextLink =\n nextResponse?.links?.next && nextLink !== nextResponse?.links?.next\n ? nextResponse.links.next\n : null;\n } catch (e) {\n this.logger.error('Failed to fetch next page of NFTs', e);\n break;\n }\n }\n\n return nfts.map((nft: Nft) => {\n try {\n nft.token_uri = Buffer.from(nft.metadata, 'base64').toString('ascii');\n } catch (e) {\n this.logger.error('Failed to decode NFT metadata', e);\n }\n return nft;\n });\n } catch (e) {\n this.logger.error('Failed to get account NFTs', e);\n return [];\n }\n }\n\n public async validateNFTOwnership(\n serialNumber: string,\n accountId: string,\n tokenId: string\n ): Promise<Nft | null> {\n const userNFTs = await this.getAccountNFTs(accountId, tokenId);\n\n return (\n userNFTs.find(\n (nft) =>\n nft.token_id === tokenId &&\n nft.serial_number.toString() === serialNumber\n ) || null\n );\n }\n\n public async readSmartContract(\n data: string,\n fromAccount: AccountId,\n contractId: ContractId,\n estimate: boolean = true,\n value: number = 0\n ): Promise<any> {\n try {\n const networkPrefix = this.getNetworkPrefix();\n const body: any = {\n block: 'latest',\n data: data,\n estimate: estimate,\n from: fromAccount.toSolidityAddress(),\n to: contractId.toSolidityAddress(),\n value,\n };\n\n if (!estimate) {\n body.gas = 300000;\n body.gasPrice = 100000000;\n }\n\n const url = `https://${networkPrefix}.mirrornode.hedera.com/api/v1/contracts/call`;\n\n const response = await fetchWithRetry()(url, {\n method: 'POST',\n body: JSON.stringify(body),\n headers: {\n 'Content-Type': 'application/json',\n },\n });\n\n if (!response.ok) {\n throw new Error(`Failed to make contract call: ${response.status}`);\n }\n\n return await response.json();\n } catch (e) {\n this.logger.error('Failed to make contract call', e);\n return null;\n }\n }\n}\n\n// This variable is replaced at build time.\n// @ts-ignore\nif ('VITE_BUILD_FORMAT' === 'umd') {\n HashinalsWalletConnectSDK.run();\n}\n\nexport * from './types';\nexport * from './sign';\nexport { \n HashinalsWalletConnectSDK, \n HashgraphSDK, \n isMobileDevice, \n isIOSDevice, \n isAndroidDevice,\n openHashPackOnMobile,\n getHashPackStoreUrl,\n checkWalletReturnUrl,\n};\n"],"names":["session","executedTx"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../src/index.ts"],"sourcesContent":["function ensureGlobalHTMLElement() {\n if (typeof globalThis === 'undefined') {\n return;\n }\n if (typeof (globalThis as any).HTMLElement === 'undefined') {\n (globalThis as any).HTMLElement = class {};\n }\n}\n\nensureGlobalHTMLElement();\n\nimport { Buffer } from 'buffer';\nimport { SessionTypes, SignClientTypes } from '@walletconnect/types';\nimport {\n Transaction,\n TransferTransaction,\n TopicMessageSubmitTransaction,\n ContractExecuteTransaction,\n Hbar,\n TransactionId,\n AccountId,\n TopicId,\n ContractId,\n LedgerId,\n TokenCreateTransaction,\n TokenType,\n TokenSupplyType,\n TokenMintTransaction,\n TopicCreateTransaction,\n TransactionReceipt,\n ContractFunctionParameters,\n PrivateKey,\n AccountCreateTransaction,\n TokenAssociateTransaction,\n TokenDissociateTransaction,\n AccountUpdateTransaction,\n AccountAllowanceApproveTransaction,\n TokenId,\n} from '@hashgraph/sdk';\nimport * as HashgraphSDK from '@hashgraph/sdk';\nimport { createAppKit } from '@reown/appkit';\nimport type { AppKit } from '@reown/appkit';\nimport {\n HederaSessionEvent,\n HederaJsonRpcMethod,\n DAppConnector,\n HederaAdapter,\n HederaChainDefinition,\n HederaChainId,\n hederaNamespace,\n HederaProvider,\n SignMessageResult,\n extensionOpen,\n ExtensionData,\n} from '@hashgraph/hedera-wallet-connect';\nimport {\n Message,\n FetchMessagesResult,\n TokenBalance,\n HederaAccountResponse,\n HederaTXResponse,\n HBarNFT,\n Nft,\n} from './types';\nimport { Logger } from './logger';\nimport { fetchWithRetry } from './utils/retry';\n\nconst HASH_PACK_WALLET_ID =\n 'a29498d225fa4b13468ff4d6cf4ae0ea4adcbd95f07ce8a843a1dee10b632f3f';\n\n/**\n * Well-known HashPack browser extension ID.\n * Used to trigger the extension popup for signing when the signer doesn't have an extensionId.\n */\nconst HASHPACK_EXTENSION_ID = 'gjagmgiddbbciopjhllkdnddhcglnemk';\n\n/**\n * HashPack deep link for mobile wallet connection\n * \n * IMPORTANT: HashPack only supports the universal link format (https://link.hashpack.app).\n * The hashpack:// custom scheme does not exist and will not work.\n */\nconst HASHPACK_DEEP_LINK = 'https://link.hashpack.app';\n\n/**\n * HashPack app store URLs for fallback when app is not installed\n */\nconst HASHPACK_STORE_URLS = {\n ios: 'https://apps.apple.com/app/hashpack/id1646514851',\n android: 'https://play.google.com/store/apps/details?id=app.hashpack.wallet',\n fallback: 'https://www.hashpack.app/',\n} as const;\n\n/**\n * Key for storing the return URL in sessionStorage.\n */\nconst WALLET_RETURN_URL_KEY = 'hashinal_wc_return_url';\n\n/**\n * Detect if current device is mobile\n */\nfunction isMobileDevice(): boolean {\n if (typeof window === 'undefined' || typeof navigator === 'undefined') {\n return false;\n }\n const userAgent = navigator.userAgent || navigator.vendor || (window as any).opera || '';\n return /android|webos|iphone|ipad|ipod|blackberry|iemobile|opera mini/i.test(userAgent.toLowerCase());\n}\n\n/**\n * Detect if device is iOS\n */\nfunction isIOSDevice(): boolean {\n if (typeof navigator === 'undefined') return false;\n return /iphone|ipad|ipod/i.test(navigator.userAgent.toLowerCase());\n}\n\n/**\n * Detect if device is Android\n */\nfunction isAndroidDevice(): boolean {\n if (typeof navigator === 'undefined') return false;\n return /android/i.test(navigator.userAgent.toLowerCase());\n}\n\n/**\n * Get the HashPack deep link for WalletConnect connections.\n * Uses the universal link format (https://link.hashpack.app) which is the only\n * supported deep link format for HashPack.\n */\nfunction getHashPackDeepLink(wcUri?: string): string {\n if (wcUri) {\n return `${HASHPACK_DEEP_LINK}/wc?uri=${encodeURIComponent(wcUri)}`;\n }\n \n return `${HASHPACK_DEEP_LINK}/wc`;\n}\n\n/**\n * Get the appropriate app store URL for the current platform\n */\nfunction getHashPackStoreUrl(): string {\n if (isIOSDevice()) return HASHPACK_STORE_URLS.ios;\n if (isAndroidDevice()) return HASHPACK_STORE_URLS.android;\n return HASHPACK_STORE_URLS.fallback;\n}\n\n/**\n * Patches all signers in the DAppConnector to have the HashPack extensionId set.\n * \n * This ensures that when DAppSigner.request() is called, it will automatically\n * trigger extensionOpen() to open the HashPack browser extension popup.\n * \n * The extensionId property is readonly in TypeScript but can be assigned at runtime\n * since JavaScript doesn't enforce readonly constraints.\n * \n * @param dAppConnector - The DAppConnector instance with signers to patch\n * @param extensionId - The extension ID to set (defaults to HashPack)\n */\nfunction patchSignersWithExtensionId(\n dAppConnector: DAppConnector | null,\n extensionId: string = HASHPACK_EXTENSION_ID\n): void {\n if (!dAppConnector?.signers?.length) return;\n if (isMobileDevice()) return;\n \n for (const signer of dAppConnector.signers) {\n if (!signer.extensionId) {\n // TypeScript says extensionId is readonly, but JavaScript allows assignment\n (signer as any).extensionId = extensionId;\n }\n }\n}\n\n/**\n * Open HashPack app on mobile device.\n * Used primarily for sign requests after a connection is already established.\n * \n * Uses a hidden anchor element to trigger the deep link without navigating\n * away from the current page. This ensures users can return to the dApp\n * after signing in the wallet.\n * \n * @param wcUri - Optional WalletConnect URI to pass to HashPack\n */\nasync function openHashPackOnMobile(wcUri?: string): Promise<void> {\n if (typeof window === 'undefined' || typeof document === 'undefined') return;\n \n try {\n sessionStorage.setItem(WALLET_RETURN_URL_KEY, window.location.href);\n } catch {\n /* sessionStorage not available */\n }\n\n const deepLink = getHashPackDeepLink(wcUri);\n \n const anchor = document.createElement('a');\n anchor.href = deepLink;\n anchor.style.display = 'none';\n anchor.setAttribute('target', '_blank');\n anchor.setAttribute('rel', 'noopener noreferrer');\n document.body.appendChild(anchor);\n anchor.click();\n document.body.removeChild(anchor);\n \n await new Promise(resolve => setTimeout(resolve, 500));\n}\n\n/**\n * Flag to track if window.open has been patched for mobile wallet deep links.\n * We only want to patch once per page load.\n */\nlet windowOpenPatched = false;\n\n/**\n * Original window.open reference, stored before patching.\n */\nlet originalWindowOpen: typeof window.open | null = null;\n\n/**\n * Patch window.open to prevent mobile wallet deep links from navigating away\n * from the current page.\n * \n * On mobile browsers, opening wallet deep links typically navigates the current\n * page away. This patch intercepts those calls and:\n * \n * 1. Saves the current URL to sessionStorage before any navigation\n * 2. Attempts to open the deep link in a way that preserves the current page\n * 3. Falls back to direct navigation if needed, but with saved state for recovery\n * \n * The dApp should check for the return URL on page load and restore if needed.\n */\nfunction patchWindowOpenForMobileWalletLinks(): void {\n if (windowOpenPatched) return;\n if (typeof window === 'undefined') return;\n \n try {\n originalWindowOpen = window.open.bind(window);\n \n window.open = function(\n url?: string | URL,\n target?: string,\n features?: string\n ): WindowProxy | null {\n const urlString = url?.toString() || '';\n const isWalletDeepLink = urlString.includes('link.hashpack.app') || \n urlString.includes('wallet.hashpack.app');\n \n if (isMobileDevice() && isWalletDeepLink && (target === '_self' || target === '_top')) {\n try {\n sessionStorage.setItem(WALLET_RETURN_URL_KEY, window.location.href);\n } catch {\n /* sessionStorage not available */\n }\n \n try {\n const newWindow = originalWindowOpen!(urlString, '_blank', 'noopener,noreferrer');\n if (newWindow) {\n return newWindow;\n }\n } catch {\n /* _blank failed, try alternative */\n }\n \n try {\n const anchor = document.createElement('a');\n anchor.href = urlString;\n anchor.target = '_blank';\n anchor.rel = 'noopener noreferrer';\n anchor.style.cssText = 'position:fixed;top:-9999px;left:-9999px;';\n document.body.appendChild(anchor);\n \n const clickEvent = new MouseEvent('click', {\n view: window,\n bubbles: true,\n cancelable: true\n });\n anchor.dispatchEvent(clickEvent);\n \n setTimeout(() => {\n try { document.body.removeChild(anchor); } catch { /* ignore */ }\n }, 100);\n \n return null;\n } catch {\n /* anchor approach failed */\n }\n \n window.location.href = urlString;\n return null;\n }\n \n return originalWindowOpen!(url, target, features);\n };\n \n windowOpenPatched = true;\n } catch {\n /* Patch failed silently - fallback to default behavior */\n }\n}\n\n/**\n * Check if there's a saved return URL from a wallet connection attempt.\n * If found, returns the URL and clears it from storage.\n * \n * dApps should call this on page load and redirect if a URL is returned.\n */\nfunction checkWalletReturnUrl(): string | null {\n if (typeof window === 'undefined') return null;\n \n try {\n const returnUrl = sessionStorage.getItem(WALLET_RETURN_URL_KEY);\n if (returnUrl) {\n sessionStorage.removeItem(WALLET_RETURN_URL_KEY);\n return returnUrl;\n }\n } catch {\n /* sessionStorage not available */\n }\n \n return null;\n}\n\n/**\n * Remove the window.open patch (for cleanup if needed)\n */\nfunction unpatchWindowOpen(): void {\n if (!windowOpenPatched || !originalWindowOpen) return;\n if (typeof window === 'undefined') return;\n \n try {\n window.open = originalWindowOpen;\n windowOpenPatched = false;\n originalWindowOpen = null;\n } catch {\n /* Unpatch failed silently */\n }\n}\n\nclass HashinalsWalletConnectSDK {\n private static instance: HashinalsWalletConnectSDK;\n private static dAppConnectorInstance: DAppConnector;\n private static proxyInstance: HashinalsWalletConnectSDK | null = null;\n private logger: Logger;\n private network: LedgerId;\n private reownAppKit: AppKit | null = null;\n private reownAppKitKey: string | null = null;\n private extensionCheckInterval: NodeJS.Timeout | null = null;\n private hasCalledExtensionCallback: boolean = false;\n private useAppKit: boolean = false;\n\n public get dAppConnector(): DAppConnector {\n return HashinalsWalletConnectSDK.dAppConnectorInstance;\n }\n\n constructor(logger?: Logger, network?: LedgerId) {\n this.logger = logger || new Logger();\n this.network = network || LedgerId.MAINNET;\n }\n\n public static getInstance(\n logger?: Logger,\n network?: LedgerId\n ): HashinalsWalletConnectSDK {\n let instance = HashinalsWalletConnectSDK?.instance;\n if (!instance) {\n HashinalsWalletConnectSDK.instance = new HashinalsWalletConnectSDK(\n logger,\n network\n );\n instance = HashinalsWalletConnectSDK.instance;\n HashinalsWalletConnectSDK.proxyInstance = null;\n }\n if (network) {\n instance.setNetwork(network);\n }\n if (!HashinalsWalletConnectSDK.proxyInstance) {\n HashinalsWalletConnectSDK.proxyInstance =\n new Proxy(instance, {\n get(target, prop, receiver) {\n const value = Reflect.get(target, prop, receiver);\n if (typeof value === 'function') {\n return value.bind(target);\n }\n return value;\n },\n }) as HashinalsWalletConnectSDK;\n }\n return HashinalsWalletConnectSDK.proxyInstance;\n }\n\n public setLogger(logger: Logger): void {\n this.logger = logger;\n }\n\n public setNetwork(network: LedgerId): void {\n this.network = network;\n }\n\n public getNetwork(): LedgerId {\n return this.network;\n }\n\n public setReownAppKit(appKit: AppKit | null): void {\n this.reownAppKit = appKit;\n }\n\n private async ensureReownAppKit(\n projectId: string,\n metadata: SignClientTypes.Metadata,\n network: LedgerId\n ): Promise<void> {\n if (typeof window === 'undefined') {\n return;\n }\n\n const key = `${projectId}:${network.toString()}`;\n if (this.reownAppKit && this.reownAppKitKey === key) {\n return;\n }\n\n try {\n const isTestnet = network.toString() === 'testnet';\n const defaultNetwork = isTestnet\n ? HederaChainDefinition.Native.Testnet\n : HederaChainDefinition.Native.Mainnet;\n\n /**\n * Create two adapters following hedera-app pattern:\n * 1. Native Hedera adapter (hederaNamespace)\n * 2. EIP155 adapter for EVM compatibility\n */\n const nativeHederaAdapter = new HederaAdapter({\n projectId,\n networks: isTestnet\n ? [HederaChainDefinition.Native.Testnet, HederaChainDefinition.Native.Mainnet]\n : [HederaChainDefinition.Native.Mainnet, HederaChainDefinition.Native.Testnet],\n namespace: hederaNamespace,\n });\n\n const eip155HederaAdapter = new HederaAdapter({\n projectId,\n networks: isTestnet\n ? [HederaChainDefinition.EVM.Testnet, HederaChainDefinition.EVM.Mainnet]\n : [HederaChainDefinition.EVM.Mainnet, HederaChainDefinition.EVM.Testnet],\n namespace: 'eip155',\n });\n\n /**\n * Create universal provider with optionalNamespaces\n * Following hedera-app pattern - HashPack only uses the first chain in the list\n */\n const providerOpts = {\n projectId,\n metadata,\n optionalNamespaces: {\n eip155: {\n methods: [\n 'eth_sendTransaction',\n 'eth_signTransaction',\n 'eth_sign',\n 'personal_sign',\n 'eth_signTypedData',\n 'eth_signTypedData_v4',\n 'eth_accounts',\n 'eth_chainId',\n ],\n chains: isTestnet\n ? ['eip155:296', 'eip155:295']\n : ['eip155:295', 'eip155:296'],\n events: ['chainChanged', 'accountsChanged'],\n rpcMap: {\n 'eip155:296': 'https://testnet.hashio.io/api',\n 'eip155:295': 'https://mainnet.hashio.io/api',\n },\n },\n hedera: {\n methods: [\n 'hedera_getNodeAddresses',\n 'hedera_executeTransaction',\n 'hedera_signMessage',\n 'hedera_signAndExecuteQuery',\n 'hedera_signAndExecuteTransaction',\n 'hedera_signTransaction',\n ],\n chains: isTestnet\n ? ['hedera:testnet', 'hedera:mainnet']\n : ['hedera:mainnet', 'hedera:testnet'],\n events: ['chainChanged', 'accountsChanged'],\n },\n },\n };\n\n const universalProvider = await HederaProvider.init(providerOpts);\n\n this.reownAppKit = createAppKit({\n adapters: [nativeHederaAdapter, eip155HederaAdapter],\n universalProvider,\n projectId,\n metadata,\n networks: [\n HederaChainDefinition.Native.Mainnet,\n HederaChainDefinition.Native.Testnet,\n HederaChainDefinition.EVM.Mainnet,\n HederaChainDefinition.EVM.Testnet,\n ],\n defaultNetwork,\n enableWalletGuide: true,\n enableWallets: true,\n enableReconnect: true,\n enableWalletConnect: false,\n allWallets: 'HIDE',\n featuredWalletIds: [HASH_PACK_WALLET_ID],\n features: {\n analytics: true,\n socials: false,\n swaps: false,\n onramp: false,\n email: false,\n },\n themeVariables: {\n '--w3m-accent': '#5599fe',\n },\n chainImages: {\n 'hedera:testnet': 'https://arweave.net/mBqmJSvl4wGWbUv3XbMHmwpjlVzO2zZCY9xPQWMwBxw',\n 'hedera:mainnet': 'https://arweave.net/mBqmJSvl4wGWbUv3XbMHmwpjlVzO2zZCY9xPQWMwBxw',\n 'eip155:296': 'https://arweave.net/mBqmJSvl4wGWbUv3XbMHmwpjlVzO2zZCY9xPQWMwBxw',\n 'eip155:295': 'https://arweave.net/mBqmJSvl4wGWbUv3XbMHmwpjlVzO2zZCY9xPQWMwBxw',\n },\n termsConditionsUrl: metadata.url ? `${metadata.url}/legal/terms` : undefined,\n privacyPolicyUrl: metadata.url ? `${metadata.url}/legal/privacy` : undefined,\n }) as AppKit;\n this.reownAppKitKey = key;\n \n patchWindowOpenForMobileWalletLinks();\n } catch (e) {\n this.logger.warn('Failed to initialize Reown AppKit', e);\n this.reownAppKit = null;\n this.reownAppKitKey = null;\n }\n }\n\n public setLogLevel(level: 'error' | 'warn' | 'info' | 'debug'): void {\n if (this.logger instanceof Logger) {\n this.logger.setLogLevel(level);\n }\n }\n\n public async init(\n projectId: string,\n metadata: SignClientTypes.Metadata,\n network?: LedgerId,\n onSessionIframeCreated?: (session: SessionTypes.Struct) => void,\n options?: { useAppKit?: boolean }\n ): Promise<DAppConnector> {\n patchWindowOpenForMobileWalletLinks();\n \n this.useAppKit = options?.useAppKit ?? false;\n \n const chosenNetwork = network || this.network;\n const isMainnet = chosenNetwork.toString() === 'mainnet';\n\n const existingConnector = HashinalsWalletConnectSDK.dAppConnectorInstance;\n if (existingConnector?.walletConnectClient) {\n return existingConnector;\n }\n\n const dAppConnector = new DAppConnector(\n metadata,\n chosenNetwork,\n projectId,\n Object.values(HederaJsonRpcMethod),\n [HederaSessionEvent.ChainChanged, HederaSessionEvent.AccountsChanged],\n [isMainnet ? HederaChainId.Mainnet : HederaChainId.Testnet],\n 'debug'\n );\n\n await dAppConnector.init({\n logger: 'error',\n });\n\n HashinalsWalletConnectSDK.dAppConnectorInstance = dAppConnector;\n\n if (this.useAppKit) {\n await this.ensureReownAppKit(projectId, metadata, chosenNetwork);\n }\n\n HashinalsWalletConnectSDK.dAppConnectorInstance.onSessionIframeCreated = (\n session\n ) => {\n this.logger.info('new session from from iframe', session);\n this.handleNewSession(session);\n patchSignersWithExtensionId(HashinalsWalletConnectSDK.dAppConnectorInstance);\n if (onSessionIframeCreated) {\n onSessionIframeCreated(session);\n }\n };\n\n this.logger.info(\n `Hedera Wallet Connect SDK initialized on ${chosenNetwork}`\n );\n \n patchSignersWithExtensionId(HashinalsWalletConnectSDK.dAppConnectorInstance);\n \n return HashinalsWalletConnectSDK.dAppConnectorInstance;\n }\n\n public async connect(options?: {\n pairingTopic?: string;\n onUri?: (uri: string) => void;\n }): Promise<SessionTypes.Struct> {\n this.ensureInitialized();\n const pairingTopic = options?.pairingTopic;\n \n // If AppKit is enabled and available, use it (for MetaMask/EVM wallet support)\n const appKit = this.useAppKit ? this.reownAppKit : null;\n if (appKit) {\n const session = await this.connectUsingReownAppKit(\n appKit,\n pairingTopic,\n options?.onUri\n );\n this.handleNewSession(session);\n patchSignersWithExtensionId(this.dAppConnector);\n return session;\n }\n\n // Simple HashPack-only flow (default)\n const availableExtension = this.getAvailableDesktopExtension();\n \n // Desktop with extension: connect directly\n if (availableExtension?.id) {\n this.logger.info('Desktop extension available, connecting directly...');\n try {\n const session = await this.dAppConnector.connectExtension(\n availableExtension.id,\n pairingTopic\n );\n this.handleNewSession(session);\n patchSignersWithExtensionId(this.dAppConnector);\n return session;\n } catch (e) {\n this.logger.warn('Direct extension connection failed, falling back to modal', e);\n }\n }\n\n // Mobile: use deep link to HashPack\n if (isMobileDevice()) {\n this.logger.info('Mobile device detected, using HashPack deep link...');\n const session = await this.dAppConnector.connect(\n (uri) => {\n openHashPackOnMobile(uri);\n },\n pairingTopic,\n undefined\n );\n this.handleNewSession(session);\n patchSignersWithExtensionId(this.dAppConnector);\n return session;\n }\n\n // Desktop without extension: use DAppConnector's built-in modal\n this.logger.info('Opening DAppConnector modal...');\n const session = await this.dAppConnector.openModal(pairingTopic);\n this.handleNewSession(session);\n patchSignersWithExtensionId(this.dAppConnector);\n return session;\n }\n\n private async connectUsingReownAppKit(\n appKit: AppKit,\n pairingTopic?: string,\n onUri?: (uri: string) => void\n ): Promise<SessionTypes.Struct> {\n this.ensureInitialized();\n if (!appKit) {\n throw new Error('AppKit instance is required.');\n }\n\n const availableExtension = this.getAvailableDesktopExtension();\n\n // Desktop with extension available: connect directly without modal\n if (availableExtension?.id) {\n this.logger.info('Desktop extension available, connecting directly...');\n try {\n const session = await this.dAppConnector.connectExtension(\n availableExtension.id,\n pairingTopic\n );\n return session;\n } catch (e) {\n this.logger.warn(\n 'Direct extension connection failed, falling back to AppKit modal',\n e\n );\n // Fall through to AppKit modal\n }\n }\n\n // Mobile: deep link to HashPack directly\n if (isMobileDevice()) {\n this.logger.info('Mobile device detected, using HashPack deep link...');\n return await this.dAppConnector.connect(\n (uri) => {\n openHashPackOnMobile(uri);\n },\n pairingTopic,\n undefined\n );\n }\n\n /**\n * Desktop without extension: Use AppKit's native connect flow\n * Following hedera-app pattern - let AppKit handle the entire UX\n */\n this.logger.info('Desktop without extension, opening AppKit Connect modal...');\n\n // Open AppKit's native connect modal with hedera namespace\n // This provides a clean UX with wallet selection, QR code, etc.\n await appKit.open({ view: 'Connect' });\n\n // Wait for the connection to be established\n // AppKit will handle showing QR codes, wallet selection, etc.\n return new Promise<SessionTypes.Struct>((resolve, reject) => {\n let resolved = false;\n const checkInterval = setInterval(() => {\n // Check if we have a new session\n const signers = this.dAppConnector?.signers || [];\n if (signers.length > 0) {\n const session = this.dAppConnector?.walletConnectClient?.session?.getAll()?.[0];\n if (session && !resolved) {\n resolved = true;\n clearInterval(checkInterval);\n void appKit.close().catch(() => {});\n resolve(session);\n }\n }\n }, 500);\n\n // Timeout after 5 minutes\n setTimeout(() => {\n if (!resolved) {\n clearInterval(checkInterval);\n void appKit.close().catch(() => {});\n reject(new Error('Connection timeout - no wallet connected'));\n }\n }, 5 * 60 * 1000);\n\n // Also listen for AppKit state changes\n const unsubscribe = appKit.subscribeState?.((state: { open?: boolean }) => {\n if (state.open === false && !resolved) {\n // Modal was closed without connecting\n clearInterval(checkInterval);\n unsubscribe?.();\n reject(new Error('Connection cancelled - modal closed'));\n }\n });\n });\n }\n\n public async disconnect(): Promise<boolean> {\n try {\n this.ensureInitialized();\n const accountInfo = this.getAccountInfo();\n const accountId = accountInfo?.accountId;\n const network = accountInfo?.network;\n const signer = this?.dAppConnector?.signers.find(\n (signer_) => signer_.getAccountId().toString() === accountId\n );\n await this.dAppConnector?.disconnect(signer?.topic);\n this.logger.info(`Disconnected from ${accountId} on ${network}`);\n return true;\n } catch (e) {\n this.logger.error('Failed to disconnect', e);\n return false;\n }\n }\n\n public async disconnectAll(): Promise<boolean> {\n try {\n this.ensureInitialized();\n await this.dAppConnector?.disconnectAll();\n this.logger.info(`Disconnected from all wallets`);\n return true;\n } catch (e) {\n this.logger.error('Failed to disconnect', e);\n return false;\n }\n }\n\n /**\n * Triggers the browser extension popup for signing on desktop.\n * This is needed when the signer doesn't have an extensionId set\n * (e.g., when connecting via the Reown AppKit modal).\n */\n private triggerExtensionPopupIfNeeded(): void {\n if (isMobileDevice()) {\n return;\n }\n\n const availableExtension = this.getAvailableDesktopExtension();\n\n if (availableExtension) {\n this.logger.debug(\n 'Triggering extension popup for signing',\n availableExtension.id\n );\n extensionOpen(availableExtension.id);\n }\n }\n\n /**\n * Gets the available desktop browser extension (e.g., HashPack).\n * Returns undefined if no extension is available or on mobile devices.\n */\n private getAvailableDesktopExtension(): ExtensionData | undefined {\n if (isMobileDevice()) {\n return undefined;\n }\n\n const extensions = this.dAppConnector?.extensions || [];\n return extensions.find((ext) => ext.available && !ext.availableInIframe);\n }\n\n public async executeTransaction(\n tx: Transaction,\n disableSigner: boolean = false\n ): Promise<TransactionReceipt> {\n this.ensureInitialized();\n const accountInfo = this.getAccountInfo();\n const accountId = accountInfo?.accountId;\n const signer = this.dAppConnector.signers.find(\n (signer_) => signer_.getAccountId().toString() === accountId\n );\n\n if (!signer) {\n throw new Error('No signer available. Please ensure wallet is connected.');\n }\n\n // Trigger wallet prompt before signing\n if (isMobileDevice()) {\n // On mobile, open HashPack app for transaction signing\n this.logger.info('Mobile device detected, opening HashPack app for transaction signing...');\n await openHashPackOnMobile();\n } else if (!signer.extensionId) {\n // On desktop, trigger extension popup if the signer doesn't have extensionId set\n // This happens when connecting via the Reown AppKit modal\n this.triggerExtensionPopupIfNeeded();\n }\n\n try {\n if (!disableSigner) {\n const signedTx = await tx.freezeWithSigner(signer);\n const executedTx = await signedTx.executeWithSigner(signer);\n return await executedTx.getReceiptWithSigner(signer);\n }\n const executedTx = await tx.executeWithSigner(signer);\n return await executedTx.getReceiptWithSigner(signer);\n } catch (e) {\n const message = (e as Error).message ?? '';\n if (message.toLowerCase().includes('nodeaccountid')) {\n throw new Error(\n 'Transaction execution failed because nodeAccountId is not set. Set node account IDs on the transaction before calling executeTransaction.'\n );\n }\n throw e;\n }\n }\n\n public async executeTransactionWithErrorHandling(\n tx: Transaction,\n disableSigner: boolean\n ): Promise<{ result?: TransactionReceipt; error?: string }> {\n try {\n const result = await this.executeTransaction(tx, disableSigner);\n return {\n result,\n error: undefined,\n };\n } catch (e) {\n const error = e as Error;\n const message = error.message?.toLowerCase();\n this.logger.error('Failed to execute transaction', e);\n this.logger.error('Failure reason for transaction is', message);\n if (message.includes('insufficient payer balance')) {\n return {\n result: undefined,\n error: 'Insufficient balance to complete the transaction.',\n };\n } else if (message.includes('reject')) {\n return {\n result: undefined,\n error: 'You rejected the transaction',\n };\n } else if (message.includes('invalid signature')) {\n return {\n result: undefined,\n error: 'Invalid signature. Please check your account and try again.',\n };\n } else if (message.includes('transaction expired')) {\n return {\n result: undefined,\n error: 'Transaction expired. Please try again.',\n };\n } else if (message.includes('account not found')) {\n return {\n result: undefined,\n error:\n 'Account not found. Please check the account ID and try again.',\n };\n } else if (message.includes('unauthorized')) {\n return {\n result: undefined,\n error:\n 'Unauthorized. You may not have the necessary permissions for this action.',\n };\n } else if (message.includes('busy')) {\n return {\n result: undefined,\n error: 'The network is busy. Please try again later.',\n };\n } else if (message.includes('invalid transaction')) {\n return {\n result: undefined,\n error: 'Invalid transaction. Please check your inputs and try again.',\n };\n }\n }\n }\n\n public async submitMessageToTopic(\n topicId: string,\n message: string,\n submitKey?: PrivateKey\n ): Promise<TransactionReceipt> {\n this.ensureInitialized();\n\n let transaction = new TopicMessageSubmitTransaction()\n .setTopicId(TopicId.fromString(topicId))\n .setMessage(message);\n\n if (submitKey) {\n transaction = await transaction.sign(submitKey);\n }\n\n return this.executeTransaction(transaction);\n }\n\n public async transferHbar(\n fromAccountId: string,\n toAccountId: string,\n amount: number\n ): Promise<TransactionReceipt> {\n this.ensureInitialized();\n\n const transaction = new TransferTransaction()\n .setTransactionId(TransactionId.generate(fromAccountId))\n .addHbarTransfer(AccountId.fromString(fromAccountId), new Hbar(-amount))\n .addHbarTransfer(AccountId.fromString(toAccountId), new Hbar(amount));\n\n return this.executeTransaction(transaction);\n }\n\n async executeSmartContract(\n contractId: string,\n functionName: string,\n parameters: ContractFunctionParameters,\n gas: number = 100000\n ): Promise<TransactionReceipt> {\n this.ensureInitialized();\n\n const transaction = new ContractExecuteTransaction()\n .setContractId(ContractId.fromString(contractId))\n .setGas(gas)\n .setFunction(functionName, parameters);\n\n return this.executeTransaction(transaction);\n }\n\n private handleNewSession(session: SessionTypes.Struct) {\n const sessionAccount = session.namespaces?.hedera?.accounts?.[0];\n const sessionParts = sessionAccount?.split(':');\n const accountId = sessionParts.pop();\n const network = sessionParts.pop();\n this.logger.info('sessionAccount is', accountId, network);\n if (!accountId) {\n this.logger.error('No account id found in the session');\n return;\n } else {\n this.saveConnectionInfo(accountId, network);\n }\n }\n\n private getNetworkPrefix(): string {\n const accountInfo = this.getAccountInfo();\n const network = accountInfo?.network;\n\n if (!network) {\n this.logger.warn('Network is not set on SDK, defaulting.');\n\n const cachedNetwork = localStorage.getItem('connectedNetwork');\n\n if (cachedNetwork) {\n return cachedNetwork;\n }\n\n return 'mainnet-public';\n }\n\n if (network !== this.network) {\n this.logger.warn(\n 'Detected network mismatch, reverting to signer network',\n network\n );\n this.network = network;\n }\n\n return network.isMainnet() ? 'mainnet-public' : 'testnet';\n }\n\n public async requestAccount(account: string): Promise<HederaAccountResponse> {\n try {\n const networkPrefix = this.getNetworkPrefix();\n\n const url = `https://${networkPrefix}.mirrornode.hedera.com/api/v1/accounts/${account}`;\n const response = await fetchWithRetry()(url);\n if (!response.ok) {\n throw new Error(\n `Failed to make request to mirror node for account: ${response.status}`\n );\n }\n return await response.json();\n } catch (e) {\n this.logger.error('Failed to fetch account', e);\n throw e;\n }\n }\n\n public async getAccountBalance(): Promise<string> {\n this.ensureInitialized();\n const accountInfo = this.getAccountInfo();\n const account = accountInfo?.accountId;\n\n if (!account) {\n return null;\n }\n\n const accountResponse = await this.requestAccount(account);\n if (!accountResponse) {\n throw new Error(\n 'Failed to fetch account. Try again or check if the Account ID is valid.'\n );\n }\n const balance = accountResponse.balance.balance / 10 ** 8;\n return Number(balance).toLocaleString('en-US');\n }\n\n public getAccountInfo(): {\n accountId: string;\n network: LedgerId;\n } {\n const { accountId: cachedAccountId } = this.loadConnectionInfo();\n if (!cachedAccountId) {\n return null;\n }\n const signers = this?.dAppConnector?.signers;\n\n if (!signers?.length) {\n return null;\n }\n\n const cachedSigner = this.dAppConnector.signers.find(\n (signer_) => signer_.getAccountId().toString() === cachedAccountId\n );\n if (!cachedSigner) {\n return null;\n }\n const accountId = cachedSigner?.getAccountId()?.toString();\n if (!accountId) {\n return null;\n }\n const network = cachedSigner.getLedgerId();\n return {\n accountId,\n network,\n };\n }\n\n public async createTopic(\n memo?: string,\n adminKey?: string,\n submitKey?: string\n ): Promise<string> {\n this.ensureInitialized();\n\n let transaction = new TopicCreateTransaction().setTopicMemo(memo || '');\n\n if (adminKey) {\n const adminWithPrivateKey = PrivateKey.fromString(adminKey);\n transaction.setAdminKey(adminWithPrivateKey.publicKey);\n transaction = await transaction.sign(adminWithPrivateKey);\n }\n\n if (submitKey) {\n transaction.setSubmitKey(PrivateKey.fromString(submitKey).publicKey);\n }\n\n const receipt = await this.executeTransaction(transaction);\n return receipt.topicId!.toString();\n }\n\n public async createToken(\n name: string,\n symbol: string,\n initialSupply: number,\n decimals: number,\n treasuryAccountId: string,\n adminKey: string,\n supplyKey: string\n ): Promise<string> {\n this.ensureInitialized();\n\n let transaction = new TokenCreateTransaction()\n .setTokenName(name)\n .setTokenSymbol(symbol)\n .setDecimals(decimals)\n .setInitialSupply(initialSupply)\n .setTreasuryAccountId(AccountId.fromString(treasuryAccountId))\n .setTokenType(TokenType.NonFungibleUnique)\n .setSupplyType(TokenSupplyType.Finite);\n\n if (supplyKey) {\n transaction = transaction.setSupplyKey(PrivateKey.fromString(supplyKey));\n }\n\n if (adminKey) {\n transaction = transaction.setAdminKey(PrivateKey.fromString(adminKey));\n transaction = await transaction.sign(PrivateKey.fromString(adminKey));\n }\n\n const receipt = await this.executeTransaction(transaction);\n return receipt.tokenId!.toString();\n }\n\n public async mintNFT(\n tokenId: string,\n metadata: string,\n supplyKey: PrivateKey\n ): Promise<TransactionReceipt> {\n this.ensureInitialized();\n\n let transaction = await new TokenMintTransaction()\n .setTokenId(tokenId)\n .setMetadata([Buffer.from(metadata, 'utf-8')])\n .sign(supplyKey);\n\n return this.executeTransaction(transaction);\n }\n\n public async getMessages(\n topicId: string,\n lastTimestamp?: number,\n disableTimestampFilter: boolean = false,\n network?: string\n ): Promise<FetchMessagesResult> {\n const networkPrefix = network || this.getNetworkPrefix();\n const baseUrl = `https://${networkPrefix}.mirrornode.hedera.com`;\n const timestampQuery =\n Number(lastTimestamp) > 0 && !disableTimestampFilter\n ? `×tamp=gt:${lastTimestamp}`\n : '';\n\n const url = `${baseUrl}/api/v1/topics/${topicId}/messages?limit=200${timestampQuery}`;\n\n try {\n const response = await fetchWithRetry()(url);\n if (!response.ok) {\n throw new Error(\n `Failed to make request to mirror node: ${response.status}`\n );\n }\n const data = await response.json();\n const messages = data?.messages || [];\n const nextLink = data?.links?.next;\n\n const collectedMessages: Message[] = messages.map((msg: any) => {\n const parsedMessage = JSON.parse(atob(msg.message));\n return {\n ...parsedMessage,\n payer: msg.payer_account_id,\n created: new Date(Number(msg.consensus_timestamp) * 1000),\n consensus_timestamp: msg.consensus_timestamp,\n sequence_number: msg.sequence_number,\n };\n });\n\n if (nextLink) {\n const nextResult = await this.getMessages(\n topicId,\n Number(\n collectedMessages[collectedMessages.length - 1]?.consensus_timestamp\n ),\n disableTimestampFilter\n );\n collectedMessages.push(...nextResult.messages);\n }\n\n return {\n messages: collectedMessages.sort(\n (a, b) => a.sequence_number - b.sequence_number\n ),\n error: '',\n };\n } catch (error) {\n this.logger.error('Error fetching topic data:', error);\n return {\n messages: [],\n error: (error as Error).toString(),\n };\n }\n }\n\n /**\n * Sign a message with the connected wallet.\n * On mobile devices, this will automatically open the HashPack app\n * to prompt the user to sign the message.\n * \n * @param message - The message to sign\n * @param options - Optional configuration for signing\n * @param options.openWalletOnMobile - Whether to open the wallet app on mobile (default: true)\n * @param options.onMobileRedirect - Callback before redirecting to wallet on mobile\n */\n public async signMessage(\n message: string,\n options?: {\n openWalletOnMobile?: boolean;\n onMobileRedirect?: () => void;\n }\n ) {\n const dAppConnector = this.dAppConnector;\n if (!dAppConnector) {\n throw new Error('No active connection or signer');\n }\n\n const accountInfo = this.getAccountInfo();\n const accountId = accountInfo?.accountId;\n\n if (!accountId) {\n throw new Error('No account connected. Please connect your wallet first.');\n }\n\n const params = {\n signerAccountId: `hedera:${this.network}:${accountId}`,\n message,\n };\n\n const shouldOpenWallet = options?.openWalletOnMobile !== false;\n if (shouldOpenWallet && isMobileDevice()) {\n this.logger.info('Mobile device detected, opening HashPack app for signing...');\n options?.onMobileRedirect?.();\n await openHashPackOnMobile();\n } else if (!isMobileDevice()) {\n // On desktop, trigger extension popup if needed\n this.triggerExtensionPopupIfNeeded();\n }\n\n try {\n const result = (await dAppConnector.signMessage(\n params\n )) as SignMessageResult;\n\n return { userSignature: (result as unknown as { signatureMap: string }).signatureMap };\n } catch (error) {\n if (isMobileDevice()) {\n const originalError = (error as Error).message || String(error);\n if (originalError.toLowerCase().includes('timeout') || \n originalError.toLowerCase().includes('reject') ||\n originalError.toLowerCase().includes('user')) {\n throw new Error(\n `Signing failed. Please make sure HashPack is open and try again. (${originalError})`\n );\n }\n }\n throw error;\n }\n }\n\n private saveConnectionInfo(\n accountId: string | undefined,\n connectedNetwork?: string | undefined\n ): void {\n if (!accountId) {\n localStorage.removeItem('connectedAccountId');\n localStorage.removeItem('connectedNetwork');\n } else {\n const cleanNetwork = connectedNetwork?.replace(/['\"]+/g, '');\n localStorage.setItem('connectedNetwork', cleanNetwork);\n localStorage.setItem('connectedAccountId', accountId);\n }\n }\n\n public loadConnectionInfo(): {\n accountId: string | null;\n network: string | null;\n } {\n return {\n accountId: localStorage.getItem('connectedAccountId'),\n network: localStorage.getItem('connectedNetwork'),\n };\n }\n\n public async connectWallet(\n PROJECT_ID: string,\n APP_METADATA: SignClientTypes.Metadata,\n network?: LedgerId,\n options?: { onUri?: (uri: string) => void; useAppKit?: boolean }\n ): Promise<{\n accountId: string;\n balance: string;\n session: SessionTypes.Struct;\n }> {\n try {\n await this.init(PROJECT_ID, APP_METADATA, network, undefined, { useAppKit: options?.useAppKit });\n const session = await this.connect({ onUri: options?.onUri });\n\n const accountInfo = this.getAccountInfo();\n const accountId = accountInfo?.accountId;\n const balance = await this.getAccountBalance();\n const networkPrefix = this.getNetworkPrefix();\n\n this.saveConnectionInfo(accountId, networkPrefix);\n return {\n accountId,\n balance,\n session,\n };\n } catch (error) {\n this.logger.error('Failed to connect wallet:', error);\n throw error;\n }\n }\n\n public async disconnectWallet(\n clearStorage: boolean = true\n ): Promise<boolean> {\n try {\n const success = await this.disconnect();\n\n if (success && clearStorage) {\n localStorage.clear();\n }\n\n this.saveConnectionInfo(undefined);\n return success;\n } catch (error) {\n this.logger.error('Failed to disconnect wallet:', error);\n return false;\n }\n }\n\n public async initAccount(\n PROJECT_ID: string,\n APP_METADATA: SignClientTypes.Metadata,\n networkOverride?: LedgerId,\n onSessionIframeCreated: (session: SessionTypes.Struct) => void = () => {},\n options?: { useAppKit?: boolean }\n ): Promise<{ accountId: string; balance: string } | null> {\n const { accountId: savedAccountId, network: savedNetwork } =\n this.loadConnectionInfo();\n\n if (savedAccountId && savedNetwork) {\n try {\n const defaultNetwork =\n savedNetwork === 'mainnet' ? LedgerId.MAINNET : LedgerId.TESTNET;\n const network = networkOverride || defaultNetwork;\n await this.init(\n PROJECT_ID,\n APP_METADATA,\n network,\n onSessionIframeCreated,\n { useAppKit: options?.useAppKit }\n );\n const balance = await this.getAccountBalance();\n return {\n accountId: savedAccountId,\n balance,\n };\n } catch (error) {\n this.logger.error('Failed to reconnect:', error);\n this.saveConnectionInfo(undefined, undefined);\n return null;\n }\n } else if (networkOverride) {\n try {\n this.logger.info(\n 'initializing normally through override.',\n networkOverride\n );\n await this.init(\n PROJECT_ID,\n APP_METADATA,\n networkOverride,\n onSessionIframeCreated,\n { useAppKit: options?.useAppKit }\n );\n this.logger.info('initialized', networkOverride);\n await this.connectViaDappBrowser();\n this.logger.info('connected via dapp browser');\n } catch (error) {\n this.logger.error('Failed to fallback connect:', error);\n this.saveConnectionInfo(undefined, undefined);\n return null;\n }\n }\n\n return null;\n }\n\n public subscribeToExtensions(callback: (extension: any) => void) {\n if (this.extensionCheckInterval) {\n clearInterval(this.extensionCheckInterval);\n }\n this.hasCalledExtensionCallback = false;\n\n this.extensionCheckInterval = setInterval(() => {\n const extensions = this.dAppConnector?.extensions || [];\n const availableExtension = extensions.find(\n (ext) => ext.availableInIframe\n );\n\n if (availableExtension && !this.hasCalledExtensionCallback) {\n this.hasCalledExtensionCallback = true;\n callback(availableExtension);\n if (this.extensionCheckInterval) {\n clearInterval(this.extensionCheckInterval);\n this.extensionCheckInterval = null;\n }\n }\n }, 1000);\n\n return () => {\n if (this.extensionCheckInterval) {\n clearInterval(this.extensionCheckInterval);\n this.extensionCheckInterval = null;\n }\n this.hasCalledExtensionCallback = false;\n };\n }\n\n public async connectViaDappBrowser() {\n const extensions = this.dAppConnector.extensions || [];\n const extension = extensions.find((ext) => {\n this.logger.info('Checking extension', ext);\n return ext.availableInIframe;\n });\n this.logger.info('extensions are', extensions, extension);\n\n if (extension) {\n await this.connectToExtension(extension);\n } else {\n // If no extension is immediately available, subscribe to changes\n this.subscribeToExtensions(async (newExtension) => {\n await this.connectToExtension(newExtension);\n });\n }\n }\n\n private async connectToExtension(extension: any) {\n this.logger.info('found extension, connecting to iframe.', extension);\n const session = await this.dAppConnector.connectExtension(extension.id);\n const onSessionIframeCreated = this.dAppConnector.onSessionIframeCreated;\n if (onSessionIframeCreated) {\n onSessionIframeCreated(session);\n }\n }\n\n private ensureInitialized(): void {\n if (!this.dAppConnector?.walletConnectClient) {\n throw new Error('WalletConnect is not initialized');\n }\n }\n\n static run(): void {\n try {\n if (typeof window !== 'undefined') {\n (window as any).HashinalsWalletConnectSDK =\n HashinalsWalletConnectSDK.getInstance();\n (window as any).HashgraphSDK = HashgraphSDK;\n }\n } catch (e) {\n console.error('[ERROR]: failed setting sdk on window');\n }\n }\n\n public async transferToken(\n tokenId: string,\n fromAccountId: string,\n toAccountId: string,\n amount: number\n ): Promise<TransactionReceipt> {\n this.ensureInitialized();\n\n const transaction = new TransferTransaction()\n .setTransactionId(TransactionId.generate(fromAccountId))\n .addTokenTransfer(\n TokenId.fromString(tokenId),\n AccountId.fromString(fromAccountId),\n -amount\n )\n .addTokenTransfer(\n TokenId.fromString(tokenId),\n AccountId.fromString(toAccountId),\n amount\n );\n\n return this.executeTransaction(transaction);\n }\n\n async createAccount(initialBalance: number): Promise<TransactionReceipt> {\n this.ensureInitialized();\n\n const transaction = new AccountCreateTransaction().setInitialBalance(\n new Hbar(initialBalance)\n );\n\n return this.executeTransaction(transaction);\n }\n\n public async associateTokenToAccount(\n accountId: string,\n tokenId: string\n ): Promise<TransactionReceipt> {\n this.ensureInitialized();\n\n const transaction = new TokenAssociateTransaction()\n .setAccountId(AccountId.fromString(accountId))\n .setTokenIds([TokenId.fromString(tokenId)]);\n\n return this.executeTransaction(transaction);\n }\n\n public async dissociateTokenFromAccount(\n accountId: string,\n tokenId: string\n ): Promise<TransactionReceipt> {\n this.ensureInitialized();\n\n const transaction = new TokenDissociateTransaction()\n .setAccountId(AccountId.fromString(accountId))\n .setTokenIds([TokenId.fromString(tokenId)]);\n\n return this.executeTransaction(transaction);\n }\n\n public async updateAccount(\n accountId: string,\n maxAutomaticTokenAssociations: number\n ): Promise<TransactionReceipt> {\n this.ensureInitialized();\n\n const transaction = new AccountUpdateTransaction()\n .setAccountId(AccountId.fromString(accountId))\n .setMaxAutomaticTokenAssociations(maxAutomaticTokenAssociations);\n\n return this.executeTransaction(transaction);\n }\n\n public async approveAllowance(\n spenderAccountId: string,\n tokenId: string,\n amount: number,\n ownerAccountId: string\n ): Promise<TransactionReceipt> {\n this.ensureInitialized();\n\n const transaction =\n new AccountAllowanceApproveTransaction().approveTokenAllowance(\n TokenId.fromString(tokenId),\n AccountId.fromString(ownerAccountId),\n AccountId.fromString(spenderAccountId),\n amount\n );\n\n return this.executeTransaction(transaction);\n }\n\n public async getAccountTokens(\n accountId: string\n ): Promise<{ tokens: TokenBalance[] }> {\n this.ensureInitialized();\n\n const networkPrefix = this.getNetworkPrefix();\n const baseUrl = `https://${networkPrefix}.mirrornode.hedera.com`;\n const url = `${baseUrl}/api/v1/accounts/${accountId}/tokens?limit=200`;\n\n try {\n const response = await fetchWithRetry()(url);\n if (!response.ok) {\n throw new Error(\n `Failed to make request to mirror node for account tokens: ${response.status}`\n );\n }\n const data = await response.json();\n\n const tokens: TokenBalance[] = [];\n\n for (const token of data.tokens) {\n if (token.token_id) {\n tokens.push({\n tokenId: token.token_id,\n balance: token.balance,\n decimals: token.decimals,\n formatted_balance: (\n token.balance /\n 10 ** token.decimals\n ).toLocaleString('en-US'),\n created_timestamp: new Date(Number(token.created_timestamp) * 1000),\n });\n }\n }\n let nextLink = data.links?.next;\n while (nextLink) {\n const nextUrl = `${baseUrl}${nextLink}`;\n const nextResponse = await fetchWithRetry()(nextUrl);\n if (!nextResponse.ok) {\n throw new Error(\n `Failed to make request to mirror node for account tokens: ${nextResponse.status}, page: ${nextUrl}`\n );\n }\n const nextData = await nextResponse.json();\n\n for (const token of nextData.tokens) {\n if (token.token_id) {\n tokens.push({\n tokenId: token.token_id,\n balance: token.balance,\n decimals: token.decimals,\n formatted_balance: (\n token.balance /\n 10 ** token.decimals\n ).toLocaleString('en-US'),\n created_timestamp: new Date(\n Number(token.created_timestamp) * 1000\n ),\n });\n }\n }\n\n nextLink = nextData.links?.next;\n }\n\n return { tokens };\n } catch (error) {\n this.logger.error('Error fetching account tokens:', error);\n throw error;\n }\n }\n\n public async getTransaction(\n transactionId: string\n ): Promise<HederaTXResponse | null> {\n try {\n const networkPrefix = this.getNetworkPrefix();\n const url = `https://${networkPrefix}.mirrornode.hedera.com/api/v1/transactions/${transactionId}`;\n\n this.logger.debug('Fetching transaction', url);\n const request = await fetchWithRetry()(url);\n\n if (!request.ok) {\n throw new Error(`Failed to fetch transaction: ${request.status}`);\n }\n\n return await request.json();\n } catch (e) {\n this.logger.error('Failed to get transaction', e);\n return null;\n }\n }\n\n public async getTransactionByTimestamp(\n timestamp: string\n ): Promise<HederaTXResponse | null> {\n try {\n const networkPrefix = this.getNetworkPrefix();\n const url = `https://${networkPrefix}.mirrornode.hedera.com/api/v1/transactions?timestamp=${timestamp}`;\n\n this.logger.debug('Fetching transaction by timestamp', url);\n const request = await fetchWithRetry()(url);\n\n if (!request.ok) {\n throw new Error(\n `Failed to fetch transaction by timestamp: ${request.status}`\n );\n }\n\n const response = (await request.json()) as HederaTXResponse;\n const transaction = response?.transactions?.[0];\n\n if (transaction) {\n return await this.getTransaction(transaction.transaction_id);\n }\n\n return null;\n } catch (e) {\n this.logger.error('Failed to get transaction by timestamp', e);\n return null;\n }\n }\n\n public async getAccountNFTs(\n accountId: string,\n tokenId?: string\n ): Promise<Nft[]> {\n try {\n const networkPrefix = this.getNetworkPrefix();\n const tokenQuery = tokenId ? `&token.id=${tokenId}` : '';\n const url = `https://${networkPrefix}.mirrornode.hedera.com/api/v1/accounts/${accountId}/nfts?limit=200${tokenQuery}`;\n\n const request = await fetchWithRetry()(url);\n if (!request.ok) {\n throw new Error(`Failed to fetch NFTs for account: ${request.status}`);\n }\n\n const response = (await request.json()) as HBarNFT;\n let nextLink: string | null = response?.links?.next || null;\n let nfts: Nft[] = (response.nfts || []) as Nft[];\n\n while (nextLink) {\n try {\n const nextRequest = await fetchWithRetry()(\n `https://${networkPrefix}.mirrornode.hedera.com${nextLink}`\n );\n\n if (!nextRequest.ok) {\n throw new Error(\n `Failed to fetch next page of NFTs: ${nextRequest.status}`\n );\n }\n\n const nextResponse = (await nextRequest.json()) as HBarNFT;\n const nextNfts = (nextResponse?.nfts || []) as Nft[];\n nfts = [...nfts, ...nextNfts];\n\n nextLink =\n nextResponse?.links?.next && nextLink !== nextResponse?.links?.next\n ? nextResponse.links.next\n : null;\n } catch (e) {\n this.logger.error('Failed to fetch next page of NFTs', e);\n break;\n }\n }\n\n return nfts.map((nft: Nft) => {\n try {\n nft.token_uri = Buffer.from(nft.metadata, 'base64').toString('ascii');\n } catch (e) {\n this.logger.error('Failed to decode NFT metadata', e);\n }\n return nft;\n });\n } catch (e) {\n this.logger.error('Failed to get account NFTs', e);\n return [];\n }\n }\n\n public async validateNFTOwnership(\n serialNumber: string,\n accountId: string,\n tokenId: string\n ): Promise<Nft | null> {\n const userNFTs = await this.getAccountNFTs(accountId, tokenId);\n\n return (\n userNFTs.find(\n (nft) =>\n nft.token_id === tokenId &&\n nft.serial_number.toString() === serialNumber\n ) || null\n );\n }\n\n public async readSmartContract(\n data: string,\n fromAccount: AccountId,\n contractId: ContractId,\n estimate: boolean = true,\n value: number = 0\n ): Promise<any> {\n try {\n const networkPrefix = this.getNetworkPrefix();\n const body: any = {\n block: 'latest',\n data: data,\n estimate: estimate,\n from: fromAccount.toSolidityAddress(),\n to: contractId.toSolidityAddress(),\n value,\n };\n\n if (!estimate) {\n body.gas = 300000;\n body.gasPrice = 100000000;\n }\n\n const url = `https://${networkPrefix}.mirrornode.hedera.com/api/v1/contracts/call`;\n\n const response = await fetchWithRetry()(url, {\n method: 'POST',\n body: JSON.stringify(body),\n headers: {\n 'Content-Type': 'application/json',\n },\n });\n\n if (!response.ok) {\n throw new Error(`Failed to make contract call: ${response.status}`);\n }\n\n return await response.json();\n } catch (e) {\n this.logger.error('Failed to make contract call', e);\n return null;\n }\n }\n}\n\n// This variable is replaced at build time.\n// @ts-ignore\nif ('VITE_BUILD_FORMAT' === 'umd') {\n HashinalsWalletConnectSDK.run();\n}\n\nexport * from './types';\nexport * from './sign';\nexport { \n HashinalsWalletConnectSDK, \n HashgraphSDK, \n isMobileDevice, \n isIOSDevice, \n isAndroidDevice,\n openHashPackOnMobile,\n getHashPackStoreUrl,\n checkWalletReturnUrl,\n};\n"],"names":["session","executedTx"],"mappings":"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"}
|