diff --git a/web/account/connected-wallet-info.css b/lib/components/connected-wallet-info.css similarity index 100% rename from web/account/connected-wallet-info.css rename to lib/components/connected-wallet-info.css diff --git a/web/account/connected-wallet-info.react.js b/lib/components/connected-wallet-info.react.js similarity index 93% rename from web/account/connected-wallet-info.react.js rename to lib/components/connected-wallet-info.react.js index ecc2a864a..f216e28e5 100644 --- a/web/account/connected-wallet-info.react.js +++ b/lib/components/connected-wallet-info.react.js @@ -1,70 +1,69 @@ // @flow import { emojiAvatarForAddress, useAccountModal } from '@rainbow-me/rainbowkit'; import * as React from 'react'; import { useAccount, useEnsAvatar } from 'wagmi'; -import SWMansionIcon from 'lib/components/SWMansionIcon.react.js'; -import { useENSName } from 'lib/hooks/ens-cache.js'; - +import { useENSName } from '../hooks/ens-cache.js'; import css from './connected-wallet-info.css'; +import SWMansionIcon from './SWMansionIcon.react.js'; function shortenAddressToFitWidth(address: string): string { if (address.length < 22) { return address; } return `${address.slice(0, 10)}…${address.slice(-10)}`; } type RainbowKitEmojiAvatar = { +color: string, +emoji: string, }; function ConnectedWalletInfo(): React.Node { const { address } = useAccount(); const { openAccountModal } = useAccountModal(); const potentiallyENSName = useENSName(address); const emojiAvatar: RainbowKitEmojiAvatar = React.useMemo( () => emojiAvatarForAddress(address), [address], ); const emojiAvatarStyle = React.useMemo( () => ({ backgroundColor: emojiAvatar.color }), [emojiAvatar.color], ); const emojiAvatarView = React.useMemo(() =>

{emojiAvatar.emoji}

, [ emojiAvatar.emoji, ]); const { data: ensAvatarURI } = useEnsAvatar({ addressOrName: potentiallyENSName, }); const potentiallyENSAvatar = React.useMemo( () => , [ensAvatarURI], ); const onClick = React.useCallback(() => { openAccountModal && openAccountModal(); }, [openAccountModal]); return (
{ensAvatarURI ? potentiallyENSAvatar : emojiAvatarView}

{shortenAddressToFitWidth(potentiallyENSName)}

); } export default ConnectedWalletInfo; diff --git a/lib/package.json b/lib/package.json index eff2f4263..3ae6df567 100644 --- a/lib/package.json +++ b/lib/package.json @@ -1,61 +1,62 @@ { "name": "lib", "version": "0.0.1", "type": "module", "private": true, "license": "BSD-3-Clause", "scripts": { "clean": "rm -rf node_modules/", "test": "jest" }, "devDependencies": { "@babel/core": "^7.13.14", "@babel/plugin-proposal-class-properties": "^7.13.0", "@babel/plugin-proposal-nullish-coalescing-operator": "^7.13.8", "@babel/plugin-proposal-object-rest-spread": "^7.13.8", "@babel/plugin-proposal-optional-chaining": "^7.13.12", "@babel/plugin-transform-runtime": "^7.13.10", "@babel/preset-env": "^7.13.12", "@babel/preset-flow": "^7.13.13", "@babel/preset-react": "^7.13.13", "@pmmmwh/react-refresh-webpack-plugin": "^0.5.10", "babel-jest": "^26.6.3", "flow-bin": "^0.182.0", "flow-typed": "^3.2.1", "react-refresh": "^0.14.0" }, "dependencies": { + "@rainbow-me/rainbowkit": "^0.5.0", "dateformat": "^3.0.3", "emoji-regex": "^10.2.1", "eth-ens-namehash": "^2.0.8", "ethers": "^5.7.2", "fast-json-stable-stringify": "^2.0.0", "file-type": "^12.3.0", "invariant": "^2.2.4", "just-clone": "^3.2.1", "lodash": "^4.17.21", "react": "18.1.0", "react-icomoon": "^2.4.1", "react-redux": "^7.1.1", "reselect": "^4.0.0", "reselect-map": "^1.0.5", "simple-markdown": "^0.7.2", "string-hash": "^1.1.3", "tcomb": "^3.2.29", "siwe": "^1.1.6", "tinycolor2": "^1.4.1", "tokenize-text": "^1.1.3", "url-parse-lax": "^3.0.0", "util-inspect": "^0.1.8", "utils-copy-error": "^1.0.1", "wagmi": "^0.6.0" }, "jest": { "transform": { "\\.js$": "babel-jest" }, "transformIgnorePatterns": [ "/node_modules/(?!@babel/runtime)" ] } } diff --git a/web/account/siwe-login-form.react.js b/web/account/siwe-login-form.react.js index 2675e4ef6..d1445a7ec 100644 --- a/web/account/siwe-login-form.react.js +++ b/web/account/siwe-login-form.react.js @@ -1,178 +1,178 @@ // @flow import '@rainbow-me/rainbowkit/dist/index.css'; import olm from '@matrix-org/olm'; import invariant from 'invariant'; import * as React from 'react'; import { useDispatch } from 'react-redux'; import { useAccount, useSigner } from 'wagmi'; import { getSIWENonce, getSIWENonceActionTypes, siweAuth, siweAuthActionTypes, } from 'lib/actions/siwe-actions'; +import ConnectedWalletInfo from 'lib/components/connected-wallet-info.react.js'; import SWMansionIcon from 'lib/components/SWMansionIcon.react.js'; import { createLoadingStatusSelector } from 'lib/selectors/loading-selectors'; import type { LogInStartingPayload } from 'lib/types/account-types.js'; import { useDispatchActionPromise, useServerCall, } from 'lib/utils/action-utils'; import { createSIWEMessage, getSIWEStatementForPublicKey, siweMessageSigningExplanationStatements, } from 'lib/utils/siwe-utils.js'; import Button from '../components/button.react'; import OrBreak from '../components/or-break.react.js'; import LoadingIndicator from '../loading-indicator.react'; import { setPrimaryIdentityPublicKey } from '../redux/primary-identity-public-key-reducer'; import { useSelector } from '../redux/redux-utils'; import { webLogInExtraInfoSelector } from '../selectors/account-selectors.js'; -import ConnectedWalletInfo from './connected-wallet-info.react.js'; import HeaderSeparator from './header-separator.react.js'; import css from './siwe.css'; type SIWELoginFormProps = { +cancelSIWEAuthFlow: () => void, }; const getSIWENonceLoadingStatusSelector = createLoadingStatusSelector( getSIWENonceActionTypes, ); function SIWELoginForm(props: SIWELoginFormProps): React.Node { const { address } = useAccount(); const { data: signer } = useSigner(); const dispatch = useDispatch(); const dispatchActionPromise = useDispatchActionPromise(); const getSIWENonceCall = useServerCall(getSIWENonce); const getSIWENonceCallLoadingStatus = useSelector( getSIWENonceLoadingStatusSelector, ); const siweAuthCall = useServerCall(siweAuth); const logInExtraInfo = useSelector(webLogInExtraInfoSelector); const [siweNonce, setSIWENonce] = React.useState(null); const siweNonceShouldBeFetched = !siweNonce && getSIWENonceCallLoadingStatus !== 'loading'; React.useEffect(() => { if (!siweNonceShouldBeFetched) { return; } dispatchActionPromise( getSIWENonceActionTypes, (async () => { const response = await getSIWENonceCall(); setSIWENonce(response); })(), ); }, [dispatchActionPromise, getSIWENonceCall, siweNonceShouldBeFetched]); const primaryIdentityPublicKey = useSelector( state => state.primaryIdentityPublicKey, ); React.useEffect(() => { (async () => { await olm.init(); const account = new olm.Account(); account.create(); const { ed25519 } = JSON.parse(account.identity_keys()); dispatch({ type: setPrimaryIdentityPublicKey, payload: ed25519, }); })(); }, [dispatch]); const callSIWEAuthEndpoint = React.useCallback( (message: string, signature: string, extraInfo) => siweAuthCall({ message, signature, ...extraInfo, }), [siweAuthCall], ); const attemptSIWEAuth = React.useCallback( (message: string, signature: string) => { const extraInfo = logInExtraInfo(); dispatchActionPromise( siweAuthActionTypes, callSIWEAuthEndpoint(message, signature, extraInfo), undefined, ({ calendarQuery: extraInfo.calendarQuery }: LogInStartingPayload), ); }, [callSIWEAuthEndpoint, dispatchActionPromise, logInExtraInfo], ); const onSignInButtonClick = React.useCallback(async () => { invariant(signer, 'signer must be present during SIWE attempt'); invariant(siweNonce, 'nonce must be present during SIWE attempt'); invariant( primaryIdentityPublicKey, 'primaryIdentityPublicKey must be present during SIWE attempt', ); const statement = getSIWEStatementForPublicKey(primaryIdentityPublicKey); const message = createSIWEMessage(address, statement, siweNonce); const signature = await signer.signMessage(message); attemptSIWEAuth(message, signature); }, [address, attemptSIWEAuth, primaryIdentityPublicKey, signer, siweNonce]); const { cancelSIWEAuthFlow } = props; const backButtonColor = React.useMemo( () => ({ backgroundColor: '#211E2D' }), [], ); if (!siweNonce || !primaryIdentityPublicKey) { return (
); } return (

Sign in with Ethereum

Wallet Connected

{siweMessageSigningExplanationStatements}

By signing up, you agree to our{' '} Terms of Use &{' '} Privacy Policy.

); } export default SIWELoginForm;