UNPKG

@hyperlane-xyz/widgets

Version:

Common react components for Hyperlane projects

131 lines 5.45 kB
import { useAccount, useConnect, useDisconnect, useNetwork, useSendTransaction, useSwitchChain, } from '@starknet-react/core'; import { useCallback, useMemo } from 'react'; import { useStarknetkitConnectModal } from 'starknetkit'; import { ProviderType, chainMetadataToStarknetChain, } from '@hyperlane-xyz/sdk'; import { ProtocolType, assert, sleep } from '@hyperlane-xyz/utils'; import { widgetLogger } from '../logger.js'; import { getChainsForProtocol } from './utils.js'; const logger = widgetLogger.child({ module: 'widgets/walletIntegrations/starknet', }); export function useStarknetAccount(_multiProvider) { const { address, isConnected } = useAccount(); return useMemo(() => ({ protocol: ProtocolType.Starknet, addresses: address ? [{ address }] : [], isReady: !!isConnected, }), [address, isConnected]); } export function useStarknetWalletDetails() { const { connector } = useAccount(); return useMemo(() => ({ name: connector?.id === 'argentX' ? 'Ready Wallet' : connector?.name || 'Starknet Wallet', logoUrl: typeof connector?.icon === 'string' ? connector.icon : connector?.icon?.light, }), [connector]); } export function useStarknetConnectFn() { const { connectAsync, connectors } = useConnect(); // This is how they do it: https://github.com/argentlabs/starknetkit-example-dapp/blob/d1d5ba8b5e06eef76b9df9b01832b57d2f22c649/src/components/connect/ConnectStarknetReactNext.tsx#L21 const { starknetkitConnectModal } = useStarknetkitConnectModal({ connectors: connectors, }); return useCallback(async () => { const { connector } = await starknetkitConnectModal(); if (connector) { await connectAsync({ connector }); } else { logger.error('No Starknet wallet connectors available'); } }, [connectAsync, starknetkitConnectModal]); } export function useStarknetDisconnectFn() { const { disconnectAsync } = useDisconnect(); return disconnectAsync; } export function useStarknetActiveChain(_multiProvider) { const { chain } = useNetwork(); return useMemo(() => ({ chainDisplayName: chain?.name, chainName: chain?.id ? chain.id.toString() : undefined, }), [chain]); } export function useStarknetSwitchNetwork(multiProvider) { const { switchChainAsync } = useSwitchChain({}); const onSwitchNetwork = useCallback(async (chainName) => { const chainId = multiProvider.getChainMetadata(chainName).chainId; try { await switchChainAsync({ chainId: chainId.toString(), }); // Some wallets seem to require a brief pause after switch await sleep(4000); } catch { // some wallets like braavos do not support chain switching logger.warn('Failed to switch chain.'); } }, [multiProvider, switchChainAsync]); return { switchNetwork: onSwitchNetwork }; } export function useStarknetWatchAsset(_multiProvider) { const onAddAsset = useCallback(async (_token, _activeChainName) => { throw new Error('Watch asset not available for starknet'); }, []); return { addAsset: onAddAsset }; } export function useStarknetTransactionFns(multiProvider) { const { account } = useAccount(); const { sendAsync } = useSendTransaction({}); const { switchNetwork } = useStarknetSwitchNetwork(multiProvider); const onSendTx = useCallback(async ({ tx, chainName, activeChainName, }) => { return onMultiSendTx({ txs: [tx], chainName, activeChainName, }); }, [account, multiProvider, switchNetwork, sendAsync]); const onMultiSendTx = useCallback(async ({ txs, chainName, activeChainName, }) => { if (txs.some((tx) => tx.type !== ProviderType.Starknet)) { throw new Error(`Invalid transaction type for Starknet: ${txs.map((tx) => tx.type).join(',')}`); } if (activeChainName && activeChainName !== chainName) { await switchNetwork(chainName); } if (!account) { throw new Error('No StarkNet account connected'); } const chainId = multiProvider.getChainMetadata(chainName).chainId; const chainIdFromWallet = await account.getChainId(); try { assert(chainIdFromWallet === chainId, `Wallet not on chain ${chainName} (ChainMismatchError)`); const result = await sendAsync(txs.map((tx) => tx.transaction)); const hash = result.transaction_hash; const confirm = async () => { const receipt = await account.waitForTransaction(hash); return { type: ProviderType.Starknet, receipt, }; }; return { hash, confirm }; } catch (error) { logger.error('Failed to send StarkNet transactions:', error); throw error; } }, [account, multiProvider, switchNetwork, sendAsync]); return { sendTransaction: onSendTx, sendMultiTransaction: onMultiSendTx, switchNetwork, }; } export function getStarknetChains(multiProvider) { return getChainsForProtocol(multiProvider, ProtocolType.Starknet).map(chainMetadataToStarknetChain); } //# sourceMappingURL=starknet.js.map