@cosmos-kit/react-lite
Version:
cosmos-kit wallet connector
103 lines (102 loc) • 4.92 kB
JavaScript
import { COSMIFRAME_KEYSTORECHANGE_EVENT, COSMIFRAME_NOT_CONNECTED_MESSAGE, } from '@cosmos-kit/core';
import { Cosmiframe, } from '@dao-dao/cosmiframe';
import { useCallback, useEffect, useRef, useState } from 'react';
import { useWallet } from './useWallet';
export const useIframe = ({ walletName, metadata, walletClientOverrides, signerOverrides, origins, } = {}) => {
const wallet = useWallet(walletName).mainWallet;
const [iframe, setIframe] = useState(null);
// Memoize these values with refs so the listener always uses their latest
// values without needing to reset.
const walletClientOverridesRef = useRef(walletClientOverrides);
walletClientOverridesRef.current = walletClientOverrides;
const signerOverridesRef = useRef(signerOverrides);
signerOverridesRef.current = signerOverrides;
const triggerKeystoreChange = useCallback(() => iframe?.contentWindow.postMessage({
event: COSMIFRAME_KEYSTORECHANGE_EVENT,
}, '*'), [iframe]);
// Broadcast keystore change event to iframe wallet.
useEffect(() => {
// Notify inner window of keystore change on any wallet client change
// (likely either connection or disconnection).
triggerKeystoreChange();
if (!wallet || typeof window === 'undefined') {
return;
}
// Notify inner window of keystore change on any wallet connect event.
wallet.walletInfo.connectEventNamesOnWindow?.forEach((eventName) => {
window.addEventListener(eventName, triggerKeystoreChange);
});
wallet.walletInfo.connectEventNamesOnClient?.forEach(async (eventName) => {
wallet.client?.on?.(eventName, triggerKeystoreChange);
});
return () => {
wallet.walletInfo.connectEventNamesOnWindow?.forEach((eventName) => {
window.removeEventListener(eventName, triggerKeystoreChange);
});
wallet.walletInfo.connectEventNamesOnClient?.forEach(async (eventName) => {
wallet.client?.off?.(eventName, triggerKeystoreChange);
});
};
}, [wallet, triggerKeystoreChange]);
// Whenever wallet changes, broadcast keystore change event to iframe wallet.
useEffect(() => {
triggerKeystoreChange();
}, [wallet, triggerKeystoreChange]);
useEffect(() => {
if (!iframe) {
return;
}
const removeListener = Cosmiframe.listen({
iframe,
target: wallet?.client || {},
getOfflineSignerDirect: wallet?.client.getOfflineSignerDirect.bind(wallet.client) ||
(() => Promise.reject(COSMIFRAME_NOT_CONNECTED_MESSAGE +
' No direct signer client function found.')),
getOfflineSignerAmino: wallet?.client.getOfflineSignerAmino.bind(wallet.client) ||
(() => Promise.reject(COSMIFRAME_NOT_CONNECTED_MESSAGE +
' No amino signer client function found.')),
nonSignerOverrides: () => ({
...walletClientOverridesRef.current,
// Override connect to return specific error.
connect: async (...params) => {
if (walletClientOverridesRef.current?.connect) {
return await walletClientOverridesRef.current.connect(params[0], params[1]);
}
else if (wallet?.client?.connect) {
await wallet.client.connect(params[0], params[1]);
}
else {
return {
type: 'error',
error: COSMIFRAME_NOT_CONNECTED_MESSAGE +
' No connect client function found or override provided.',
};
}
},
}),
signerOverrides: async (chainId) => typeof signerOverridesRef.current === 'function'
? signerOverridesRef.current(chainId)
: signerOverridesRef.current,
origins,
metadata: {
name: metadata?.name || `${wallet.walletInfo.prettyName} (Outer Wallet)`,
imageUrl: metadata?.imageUrl ||
(wallet.walletInfo.logo
? typeof wallet.walletInfo.logo === 'string'
? wallet.walletInfo.logo
: 'major' in wallet.walletInfo.logo
? wallet.walletInfo.logo.major
: undefined
: undefined),
},
});
return removeListener;
}, [iframe, wallet, metadata, origins]);
const iframeRef = useCallback((iframe) => setIframe(iframe), []);
return {
wallet,
iframeRef,
iframe,
triggerKeystoreChange,
};
};