@hyperlane-xyz/widgets
Version:
Common react components for Hyperlane projects
131 lines • 5.45 kB
JavaScript
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