@sky-mavis/tanto-widget
Version:
Tanto Widget
126 lines (122 loc) • 3.97 kB
JavaScript
;
var jsxRuntime = require('@emotion/react/jsx-runtime');
var reactQuery = require('@tanstack/react-query');
var react = require('react');
var uuid = require('uuid');
var wagmi = require('wagmi');
var useAccountSwitch = require('../../hooks/useAccountSwitch.cjs');
var useAuthEffect = require('../../hooks/useAuthEffect.cjs');
var queries = require('../../services/queries.cjs');
var common = require('../../utils/common.cjs');
var errors = require('../../utils/errors.cjs');
var siwe = require('../../utils/siwe.cjs');
var walletDetection = require('../../utils/walletDetection.cjs');
var useTantoConfig = require('../tanto/useTantoConfig.cjs');
var AuthContext = require('./AuthContext.cjs');
var useWaypointMessageHandler = require('./useWaypointMessageHandler.cjs');
function AuthProvider({
children
}) {
const {
createAccountOnConnect: enableAuth = false,
clientId,
__internal_baseUrl
} = useTantoConfig.useTantoConfig();
const {
address,
chainId,
connector
} = wagmi.useAccount();
const {
signMessageAsync
} = wagmi.useSignMessage();
const {
disconnect
} = wagmi.useDisconnect();
const [isSigningIn, setIsSigningIn] = react.useState(false);
const [error, setError] = react.useState(null);
const currentSignInRef = react.useRef(null);
const {
mutateAsync: generateNonce
} = reactQuery.useMutation(queries.mutation.generateNonce());
const {
mutateAsync: createAccount
} = reactQuery.useMutation(queries.mutation.createAccount());
const reset = react.useCallback(() => {
setIsSigningIn(false);
setError(null);
currentSignInRef.current = null;
}, []);
const signIn = react.useCallback(async () => {
if (!enableAuth || !address || !chainId || isSigningIn) return;
const sessionId = uuid.v4();
currentSignInRef.current = sessionId;
setIsSigningIn(true);
setError(null);
try {
// Wait for WC (in case of connect to metamask) switch chain
if (walletDetection.isWCConnector(connector?.id)) await common.delay(1_000);
if (walletDetection.isWaypointConnector(connector?.id)) return;
const {
nonce,
expirationTime,
issuedAt,
notBefore
} = await generateNonce({
baseUrl: __internal_baseUrl,
address,
clientId
});
const message = siwe.generateSiweMessage({
address,
chainId,
nonce,
expirationTime,
issuedAt,
notBefore
});
const signature = await signMessageAsync({
message
});
if (currentSignInRef.current !== sessionId) return;
const {
idToken
} = await createAccount({
baseUrl: __internal_baseUrl,
message,
signature,
clientId
});
useAuthEffect.authEventEmitter.emit('success', {
address,
chainId,
token: idToken
});
} catch (error) {
if (currentSignInRef.current !== sessionId) return;
const authError = error instanceof Error ? error : new errors.TantoWidgetError(errors.TantoWidgetErrorCodes.CREATE_ACCOUNT_FAILED, 'Failed to create account');
console.debug('Auth error:', authError);
setError(authError);
useAuthEffect.authEventEmitter.emit('failed', {
error: authError
});
disconnect();
} finally {
setIsSigningIn(false);
}
}, [enableAuth, address, chainId, isSigningIn, connector?.id, generateNonce, signMessageAsync, createAccount, clientId, disconnect]);
useAccountSwitch.useAccountSwitch(signIn);
useWaypointMessageHandler.useWaypointMessageHandler(enableAuth);
const contextValue = react.useMemo(() => ({
enable: enableAuth,
error,
isSigningIn,
signIn,
reset
}), [enableAuth, error, isSigningIn, signIn, reset]);
return jsxRuntime.jsx(AuthContext.AuthContext.Provider, {
value: contextValue,
children: children
});
}
exports.AuthProvider = AuthProvider;