@web3auth/no-modal
Version:
Multi chain wallet aggregator for web3Auth
207 lines (203 loc) • 8.39 kB
JavaScript
'use strict';
var _objectSpread = require('@babel/runtime/helpers/objectSpread2');
var _objectWithoutProperties = require('@babel/runtime/helpers/objectWithoutProperties');
var client = require('@solana/client');
var reactHooks = require('@solana/react-hooks');
var react = require('react');
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');
require('../context/Web3AuthInnerContext.js');
var useChain = require('../hooks/useChain.js');
require('../context/WalletServicesInnerContext.js');
var useWeb3Auth = require('../hooks/useWeb3Auth.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 === baseControllers.CHAIN_NAMESPACES.SOLANA);
const current = web3Auth.currentChain;
const chain = (current === null || current === void 0 ? void 0 : current.chainNamespace) === baseControllers.CHAIN_NAMESPACES.SOLANA ? current : solanaChains[0];
if (!chain) return {
rpcTarget: DEVNET_ENDPOINT
};
return {
rpcTarget: chain.rpcTarget,
wsTarget: chain.wsTarget
};
}
function makePlaceholder(rpc) {
return client.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) === 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$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 === baseControllers.CHAIN_NAMESPACES.SOLANA && utils.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 === baseControllers.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.useWeb3Auth();
const {
chainId,
chainNamespace
} = useChain.useChain();
const solClientRef = react.useRef(null);
const connectedClientRef = react.useRef(null);
const [client$1, setClient] = react.useState(() => {
const c = makePlaceholder({
rpcTarget: DEVNET_ENDPOINT
});
solClientRef.current = c;
return c;
});
react.useEffect(() => {
if (isInitialized) web3Auth === null || web3Auth === void 0 || web3Auth.setAnalyticsProperties({
solana_framework_kit_enabled: true
});
}, [isInitialized, web3Auth]);
react.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;
}, []);
react.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) !== baseControllers.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 = client.createWalletStandardConnector(conn.solanaWallet, {
id: solanaWalletId,
name: conn.connectorName
});
const {
rpcTarget,
wsTarget
} = preferredSolanaChain;
const wired = client.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 === baseControllers.CHAIN_NAMESPACES.SOLANA && (currentChain === null || currentChain === void 0 ? void 0 : currentChain.chainNamespace) === baseControllers.CHAIN_NAMESPACES.SOLANA) {
adopt(wired);
} else {
adopt(makePlaceholder(rpc));
}
if (prevConnectedClient && prevConnectedClient !== wired) {
dispose(prevConnectedClient);
}
} catch (e) {
loglevel.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$1;
}
function SolanaProvider(_ref) {
let {
children
} = _ref,
props = _objectWithoutProperties(_ref, _excluded);
const client = useFrameworkKitSolanaClient();
return react.createElement(reactHooks.SolanaProvider, _objectSpread(_objectSpread({}, props), {}, {
client,
walletPersistence: false,
children
}));
}
exports.SolanaProvider = SolanaProvider;