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
);
}
export default SIWELoginForm;