UNPKG

@hyperlane-xyz/widgets

Version:

Common react components for Hyperlane projects

101 lines 4.24 kB
import { useConnection, useWallet } from '@solana/wallet-adapter-react'; import { useWalletModal } from '@solana/wallet-adapter-react-ui'; import { Connection } from '@solana/web3.js'; import { useCallback, useMemo } from 'react'; import { ProviderType, } from '@hyperlane-xyz/sdk'; import { ProtocolType } from '@hyperlane-xyz/utils'; import { widgetLogger } from '../logger.js'; import { findChainByRpcUrl } from './utils.js'; const logger = widgetLogger.child({ module: 'walletIntegrations/solana' }); export function useSolanaAccount(_multiProvider) { const { publicKey, connected, wallet } = useWallet(); const isReady = !!(publicKey && wallet && connected); const address = publicKey?.toBase58(); return useMemo(() => ({ protocol: ProtocolType.Sealevel, addresses: address ? [{ address: address }] : [], isReady: isReady, }), [address, isReady]); } export function useSolanaWalletDetails() { const { wallet } = useWallet(); const { name, icon } = wallet?.adapter || {}; return useMemo(() => ({ name, logoUrl: icon, }), [name, icon]); } export function useSolanaConnectFn() { const { setVisible } = useWalletModal(); return useCallback(() => setVisible(true), [setVisible]); } export function useSolanaDisconnectFn() { const { disconnect } = useWallet(); return disconnect; } export function useSolanaActiveChain(multiProvider) { const { connection } = useConnection(); const connectionEndpoint = connection?.rpcEndpoint; return useMemo(() => { try { const hostname = new URL(connectionEndpoint).hostname; const metadata = findChainByRpcUrl(multiProvider, hostname); if (!metadata) return {}; return { chainDisplayName: metadata.displayName, chainName: metadata.name, }; } catch (error) { logger.warn('Error finding sol active chain', error); return {}; } }, [connectionEndpoint, multiProvider]); } export function useSolanaSwitchNetwork() { const onSwitchNetwork = useCallback(async (chainName) => { logger.warn(`Solana wallet must be connected to origin chain ${chainName}`); }, []); return { switchNetwork: onSwitchNetwork }; } export function useSolanaWatchAsset(_multiProvider) { const onAddAsset = useCallback(async (_token, _activeChainName) => { throw new Error('Watch asset not available for solana'); }, []); return { addAsset: onAddAsset }; } export function useSolanaTransactionFns(multiProvider) { const { sendTransaction: sendSolTransaction } = useWallet(); const { switchNetwork } = useSolanaSwitchNetwork(); const onSendTx = useCallback(async ({ tx, chainName, activeChainName, }) => { if (tx.type !== ProviderType.SolanaWeb3) throw new Error(`Unsupported tx type: ${tx.type}`); if (activeChainName && activeChainName !== chainName) await switchNetwork(chainName); const rpcUrl = multiProvider.getRpcUrl(chainName); const connection = new Connection(rpcUrl, 'confirmed'); const { context: { slot: minContextSlot }, value: { blockhash, lastValidBlockHeight }, } = await connection.getLatestBlockhashAndContext(); logger.debug(`Sending tx on chain ${chainName}`); const signature = await sendSolTransaction(tx.transaction, connection, { minContextSlot, }); const confirm = () => connection .confirmTransaction({ blockhash, lastValidBlockHeight, signature }) .then(() => connection.getTransaction(signature)) .then((r) => ({ type: ProviderType.SolanaWeb3, receipt: r, })); return { hash: signature, confirm }; }, [switchNetwork, sendSolTransaction, multiProvider]); const onMultiSendTx = useCallback(async ({ txs: _, chainName: __, activeChainName: ___, }) => { throw new Error('Multi Transactions not supported on Solana'); }, []); return { sendTransaction: onSendTx, sendMultiTransaction: onMultiSendTx, switchNetwork, }; } //# sourceMappingURL=solana.js.map