UNPKG

@web3auth/no-modal

Version:
169 lines (165 loc) 7.66 kB
'use strict'; var client = require('@solana/client'); var vue = require('vue'); require('@babel/runtime/helpers/objectSpread2'); require('@babel/runtime/helpers/defineProperty'); require('@segment/analytics-next'); var loglevel = require('../../base/loglevel.js'); var baseControllers = require('@toruslabs/base-controllers'); require('@toruslabs/session-manager'); require('@web3auth/auth'); require('../../base/errors/index.js'); var utils = require('../../base/utils.js'); require('../../base/wallet/index.js'); require('../../base/connector/connectorStatus.js'); require('../../base/connector/constants.js'); require('jwt-decode'); require('../../base/constants.js'); require('../../base/plugin/errors.js'); require('../../base/plugin/IPlugin.js'); var useChain = require('../composables/useChain.js'); var useWeb3Auth = require('../composables/useWeb3Auth.js'); var constants = require('./constants.js'); const disposeClient = async client => { client.destroy(); }; const resolveSolanaChain = (web3Auth, connection) => { var _web3Auth$coreOptions2; const currentChain = web3Auth === null || web3Auth === void 0 ? void 0 : web3Auth.currentChain; if ((currentChain === null || currentChain === void 0 ? void 0 : currentChain.chainNamespace) === baseControllers.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$coreOptions; const connectedChain = web3Auth === null || web3Auth === void 0 || (_web3Auth$coreOptions = web3Auth.coreOptions.chains) === null || _web3Auth$coreOptions === void 0 ? void 0 : _web3Auth$coreOptions.find(chain => { return chain.chainNamespace === baseControllers.CHAIN_NAMESPACES.SOLANA && utils.getCaipChainId(chain) === connectedScope; }); if (connectedChain) return connectedChain; } return (web3Auth === null || web3Auth === void 0 || (_web3Auth$coreOptions2 = web3Auth.coreOptions.chains) === null || _web3Auth$coreOptions2 === void 0 ? void 0 : _web3Auth$coreOptions2.find(chain => chain.chainNamespace === baseControllers.CHAIN_NAMESPACES.SOLANA)) || null; }; /** * Syncs Web3Auth Solana connection with Framework Kit client. * For multichain wallets, keep the Solana client warm across namespace switches so * switching back to Solana can reuse the existing wallet session. */ const SolanaProvider = vue.defineComponent({ name: "SolanaProvider", setup(_, { slots }) { const { isConnected, connection, web3Auth } = useWeb3Auth.useWeb3Auth(); const { chainId } = useChain.useChain(); const clientRef = vue.ref(null); let connectedClient = null; // let connectedClientKey: string | null = null; // Holds the token for the newest requested sync run. Older async runs compare against it // before publishing results so a slower reconnect cannot overwrite a newer chain/account update. let activeSyncToken = null; // provide the client to the app vue.provide(constants.SOLANA_CLIENT_KEY, clientRef); const syncClient = async () => { var _web3Auth$value, _web3Auth$value2; // Only the latest async, `syncing` run should be allowed to attach its client. // A fresh Symbol gives each run a unique identity without relying on counters. const syncToken = Symbol("solana-client-sync"); activeSyncToken = syncToken; const newIsConnected = isConnected.value; const newConnection = connection.value; const currentChain = (_web3Auth$value = web3Auth.value) === null || _web3Auth$value === void 0 ? void 0 : _web3Auth$value.currentChain; if ((currentChain === null || currentChain === void 0 ? void 0 : currentChain.chainNamespace) !== baseControllers.CHAIN_NAMESPACES.SOLANA) { // Mirror the React provider behavior: hide the live Solana client from injected // consumers whenever Web3Auth is currently scoped to a non-Solana namespace. clientRef.value = null; return; } const preferredSolanaChain = resolveSolanaChain(web3Auth.value, newConnection); const shouldKeepSolanaClient = newIsConnected && Boolean(newConnection === null || newConnection === void 0 ? void 0 : newConnection.solanaWallet) && Boolean(preferredSolanaChain) && // only manage the client for the primary connector (newConnection === null || newConnection === void 0 ? void 0 : newConnection.connectorName) === ((_web3Auth$value2 = web3Auth.value) === null || _web3Auth$value2 === void 0 ? void 0 : _web3Auth$value2.primaryConnectorName); if (!shouldKeepSolanaClient) { clientRef.value = null; const prevClient = connectedClient; connectedClient = null; // connectedClientKey = null; if (prevClient) { await disposeClient(prevClient); } return; } let client$1 = null; try { // create a wallet standard connector from connected wallet const solanaWalletId = "wallet-standard:" + newConnection.connectorName; const connector = client.createWalletStandardConnector(newConnection.solanaWallet, { id: solanaWalletId, name: newConnection.connectorName }); // create a solana client const { rpcTarget, wsTarget } = preferredSolanaChain; client$1 = client.createClient({ endpoint: rpcTarget, websocketEndpoint: wsTarget, walletConnectors: [connector] }); // connect the client to the wallet await client$1.actions.connectWallet(solanaWalletId, { autoConnect: true }); // If another sync started while connectWallet was in flight, this client is stale. if (activeSyncToken !== syncToken) { await disposeClient(client$1); return; } const prevClient = connectedClient; connectedClient = client$1; // connectedClientKey = nextClientKey; clientRef.value = (currentChain === null || currentChain === void 0 ? void 0 : currentChain.chainNamespace) === baseControllers.CHAIN_NAMESPACES.SOLANA ? client$1 : null; if (prevClient) { await disposeClient(prevClient); } } catch (err) { if (client$1) { await disposeClient(client$1); } loglevel.log.error("Failed to create or connect Solana client", err); // Only clear the shared ref when this failing run is still the newest one. if (activeSyncToken === syncToken) { clientRef.value = null; } } }; // watch for changes in the connection and active chain vue.watch([isConnected, connection, chainId], () => { void syncClient(); }, { immediate: true }); vue.onBeforeUnmount(() => { const publishedClient = clientRef.value; clientRef.value = null; const prevClient = connectedClient; connectedClient = null; if (prevClient) { void disposeClient(prevClient); } else if (publishedClient) { void disposeClient(publishedClient); } }); return () => { var _slots$default, _slots$default2; return vue.h(vue.Fragment, null, (_slots$default = (_slots$default2 = slots.default) === null || _slots$default2 === void 0 ? void 0 : _slots$default2.call(slots)) !== null && _slots$default !== void 0 ? _slots$default : []); }; } }); exports.SolanaProvider = SolanaProvider;