UNPKG

@web3auth/no-modal

Version:
192 lines (188 loc) 7.66 kB
import _objectSpread from '@babel/runtime/helpers/objectSpread2'; import _objectWithoutProperties from '@babel/runtime/helpers/objectWithoutProperties'; import { createWalletStandardConnector, createClient } from '@solana/client'; import { SolanaProvider as SolanaProvider$1 } from '@solana/react-hooks'; import { createElement, useRef, useState, useEffect } from 'react'; import { useWeb3Auth } from '../hooks/useWeb3Auth.js'; import { useChain } from '../hooks/useChain.js'; import { CHAIN_NAMESPACES } from '@toruslabs/base-controllers'; import { log } from '../../base/loglevel.js'; import { getCaipChainId } from '../../base/utils.js'; const _excluded = ["children"]; const DEVNET_ENDPOINT = "https://api.devnet.solana.com"; function placeholderRpc(isInitialized, web3Auth) { var _web3Auth$coreOptions; if (!isInitialized || !(web3Auth !== null && web3Auth !== void 0 && (_web3Auth$coreOptions = web3Auth.coreOptions) !== null && _web3Auth$coreOptions !== void 0 && _web3Auth$coreOptions.chains)) { return { rpcTarget: DEVNET_ENDPOINT }; } const solanaChains = web3Auth.coreOptions.chains.filter(c => c.chainNamespace === CHAIN_NAMESPACES.SOLANA); const current = web3Auth.currentChain; const chain = (current === null || current === void 0 ? void 0 : current.chainNamespace) === CHAIN_NAMESPACES.SOLANA ? current : solanaChains[0]; if (!chain) return { rpcTarget: DEVNET_ENDPOINT }; return { rpcTarget: chain.rpcTarget, wsTarget: chain.wsTarget }; } function makePlaceholder(rpc) { return createClient({ endpoint: rpc.rpcTarget, websocketEndpoint: rpc.wsTarget, walletConnectors: [] }); } function dispose(client) { client.destroy(); } function resolveSolanaChain(web3Auth, connection) { var _web3Auth$coreOptions3; const currentChain = web3Auth === null || web3Auth === void 0 ? void 0 : web3Auth.currentChain; if ((currentChain === null || currentChain === void 0 ? void 0 : currentChain.chainNamespace) === CHAIN_NAMESPACES.SOLANA) { return currentChain; } const connectedScope = connection !== null && connection !== void 0 && connection.solanaWallet && "scope" in connection.solanaWallet && typeof connection.solanaWallet.scope === "string" ? connection.solanaWallet.scope : null; if (connectedScope) { var _web3Auth$coreOptions2; const connectedChain = web3Auth === null || web3Auth === void 0 || (_web3Auth$coreOptions2 = web3Auth.coreOptions.chains) === null || _web3Auth$coreOptions2 === void 0 ? void 0 : _web3Auth$coreOptions2.find(chain => { return chain.chainNamespace === CHAIN_NAMESPACES.SOLANA && getCaipChainId(chain) === connectedScope; }); if (connectedChain) return connectedChain; } return (web3Auth === null || web3Auth === void 0 || (_web3Auth$coreOptions3 = web3Auth.coreOptions.chains) === null || _web3Auth$coreOptions3 === void 0 ? void 0 : _web3Auth$coreOptions3.find(chain => chain.chainNamespace === CHAIN_NAMESPACES.SOLANA)) || null; } /** * Builds the SolanaClient for Framework Kit React hooks. * For multichain wallets, keep the Solana client warm across namespace switches so * switching back to Solana can reuse the existing wallet session. */ function useFrameworkKitSolanaClient() { const { isConnected, connection, web3Auth, isInitialized } = useWeb3Auth(); const { chainId, chainNamespace } = useChain(); const solClientRef = useRef(null); const connectedClientRef = useRef(null); const [client, setClient] = useState(() => { const c = makePlaceholder({ rpcTarget: DEVNET_ENDPOINT }); solClientRef.current = c; return c; }); useEffect(() => { if (isInitialized) web3Auth === null || web3Auth === void 0 || web3Auth.setAnalyticsProperties({ solana_framework_kit_enabled: true }); }, [isInitialized, web3Auth]); useEffect(() => () => { const connectedClient = connectedClientRef.current; const currentClient = solClientRef.current; if (currentClient) { dispose(currentClient); solClientRef.current = null; } if (connectedClient && connectedClient !== currentClient) { dispose(connectedClient); } connectedClientRef.current = null; }, []); useEffect(() => { let stale = false; const adopt = nextClient => { if (stale) { dispose(nextClient); return; } const prevClient = solClientRef.current; if (prevClient === nextClient) return; if (prevClient) dispose(prevClient); solClientRef.current = nextClient; setClient(nextClient); }; (async () => { const rpc = placeholderRpc(isInitialized, web3Auth); const conn = connection; const currentChain = web3Auth === null || web3Auth === void 0 ? void 0 : web3Auth.currentChain; if ((currentChain === null || currentChain === void 0 ? void 0 : currentChain.chainNamespace) !== CHAIN_NAMESPACES.SOLANA) { adopt(makePlaceholder(rpc)); return; } const preferredSolanaChain = resolveSolanaChain(web3Auth, conn); const shouldKeepSolanaClient = isConnected && Boolean(conn === null || conn === void 0 ? void 0 : conn.solanaWallet) && Boolean(preferredSolanaChain) && // only manage the client for the primary connector (conn === null || conn === void 0 ? void 0 : conn.connectorName) === (web3Auth === null || web3Auth === void 0 ? void 0 : web3Auth.primaryConnectorName); if (!shouldKeepSolanaClient) { const connectedClient = connectedClientRef.current; connectedClientRef.current = null; if (connectedClient) { dispose(connectedClient); } adopt(makePlaceholder(rpc)); return; } try { const solanaWalletId = "wallet-standard:" + conn.connectorName; const connector = createWalletStandardConnector(conn.solanaWallet, { id: solanaWalletId, name: conn.connectorName }); const { rpcTarget, wsTarget } = preferredSolanaChain; const wired = createClient({ endpoint: rpcTarget, websocketEndpoint: wsTarget, walletConnectors: [connector] }); await wired.actions.connectWallet(solanaWalletId, { autoConnect: true }); if (stale) { dispose(wired); return; } const prevConnectedClient = connectedClientRef.current; connectedClientRef.current = wired; if (chainNamespace === CHAIN_NAMESPACES.SOLANA && (currentChain === null || currentChain === void 0 ? void 0 : currentChain.chainNamespace) === CHAIN_NAMESPACES.SOLANA) { adopt(wired); } else { adopt(makePlaceholder(rpc)); } if (prevConnectedClient && prevConnectedClient !== wired) { dispose(prevConnectedClient); } } catch (e) { log.error("Failed to create or connect Solana client", e); adopt(makePlaceholder(rpc)); } })(); return () => { stale = true; }; }, [isConnected, connection === null || connection === void 0 ? void 0 : connection.solanaWallet, chainId, chainNamespace, web3Auth, isInitialized, connection === null || connection === void 0 ? void 0 : connection.connectorName]); return client; } function SolanaProvider(_ref) { let { children } = _ref, props = _objectWithoutProperties(_ref, _excluded); const client = useFrameworkKitSolanaClient(); return createElement(SolanaProvider$1, _objectSpread(_objectSpread({}, props), {}, { client, walletPersistence: false, children })); } export { SolanaProvider };