Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F32213076
D14911.1765145835.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Size
25 KB
Referenced Files
None
Subscribers
None
D14911.1765145835.diff
View Options
diff --git a/lib/actions/user-actions.js b/lib/actions/user-actions.js
--- a/lib/actions/user-actions.js
+++ b/lib/actions/user-actions.js
@@ -934,6 +934,7 @@
siweMessage: string,
siweSignature: string,
fid: ?string,
+ farcasterDCsToken: ?string,
) => Promise<IdentityAuthResult> {
const client = React.useContext(IdentityClientContext);
const identityClient = client?.identityClient;
diff --git a/lib/types/siwe-types.js b/lib/types/siwe-types.js
--- a/lib/types/siwe-types.js
+++ b/lib/types/siwe-types.js
@@ -128,6 +128,7 @@
+message: string,
+signature: string,
+fid?: ?string,
+ +farcasterDCsToken?: ?string,
};
export const SIWEMessageTypes = Object.freeze({
diff --git a/lib/utils/services-utils.js b/lib/utils/services-utils.js
--- a/lib/utils/services-utils.js
+++ b/lib/utils/services-utils.js
@@ -14,6 +14,8 @@
// an authoritative keyserver for things like DMs.
const relyingOnAuthoritativeKeyserver = true;
+const supportsFarcasterDCs = false;
+
// If this returns true, then we're using the login 2.0, which means that a user
// can either restore an account (primary login) or log in using the QR code
// (secondary login).
@@ -64,4 +66,5 @@
httpResponseIsInvalidCSAT,
errorMessageIsInvalidCSAT,
fullBackupSupport,
+ supportsFarcasterDCs,
};
diff --git a/native/.eslintrc.json b/native/.eslintrc.json
--- a/native/.eslintrc.json
+++ b/native/.eslintrc.json
@@ -2,6 +2,9 @@
"env": {
"react-native/react-native": true
},
+ "globals": {
+ "URLSearchParams": "readonly"
+ },
"plugins": ["react-native"],
"rules": {
"react-native/no-unused-styles": 2,
diff --git a/native/account/registration/auth-navigator.react.js b/native/account/registration/auth-navigator.react.js
--- a/native/account/registration/auth-navigator.react.js
+++ b/native/account/registration/auth-navigator.react.js
@@ -25,6 +25,7 @@
} from './auth-router.js';
import AvatarSelection from './avatar-selection.react.js';
import ConnectEthereum from './connect-ethereum.react.js';
+import { ConnectFarcasterDCs } from './connect-farcaster-dcs.react.js';
import ConnectFarcaster from './connect-farcaster.react.js';
import CoolOrNerdModeSelection from './cool-or-nerd-mode-selection.react.js';
import EmojiAvatarSelection from './emoji-avatar-selection.react.js';
@@ -59,6 +60,7 @@
RestoreBackupScreenRouteName,
RestoreBackupErrorScreenRouteName,
RestoreSIWEBackupRouteName,
+ ConnectFarcasterDCsRouteName,
} from '../../navigation/route-names.js';
import QRCodeScreen from '../qr-code-screen.react.js';
import RestoreBackupErrorScreen from '../restore-backup-error-screen.react.js';
@@ -234,6 +236,10 @@
name={RestoreSIWEBackupRouteName}
component={RestoreSIWEBackup}
/>
+ <Auth.Screen
+ name={ConnectFarcasterDCsRouteName}
+ component={ConnectFarcasterDCs}
+ />
</Auth.Navigator>
);
}
diff --git a/native/account/registration/avatar-selection.react.js b/native/account/registration/avatar-selection.react.js
--- a/native/account/registration/avatar-selection.react.js
+++ b/native/account/registration/avatar-selection.react.js
@@ -41,6 +41,7 @@
+accountSelection: AccountSelection,
+farcasterID: ?string,
+farcasterAvatarURL: ?string,
+ +farcasterDCsToken: ?string,
},
};
diff --git a/native/account/registration/connect-ethereum.react.js b/native/account/registration/connect-ethereum.react.js
--- a/native/account/registration/connect-ethereum.react.js
+++ b/native/account/registration/connect-ethereum.react.js
@@ -48,6 +48,7 @@
+keyserverURL?: ?string,
+farcasterID: ?string,
+farcasterAvatarURL: ?string,
+ +farcasterDCsToken: ?string,
},
};
diff --git a/native/account/registration/connect-farcaster-dcs.react.js b/native/account/registration/connect-farcaster-dcs.react.js
new file mode 100644
--- /dev/null
+++ b/native/account/registration/connect-farcaster-dcs.react.js
@@ -0,0 +1,246 @@
+// @flow
+
+import invariant from 'invariant';
+import * as React from 'react';
+
+import type { AuthNavigationProp } from './auth-navigator.react.js';
+import { siweNonceExpired } from './ethereum-utils.js';
+import { RegistrationContext } from './registration-context.js';
+import RegistrationTextInput from './registration-text-input.react.js';
+import type { CoolOrNerdMode } from './registration-types.js';
+import FarcasterPrompt from '../../components/farcaster-prompt.react.js';
+import PrimaryButton from '../../components/primary-button.react.js';
+import { FarcasterAuthContextProvider } from '../../farcaster-auth/farcaster-auth-context-provider.react.js';
+import { useGetAuthToken } from '../../farcaster-auth/farcaster-auth-utils.js';
+import type { NavigationRoute } from '../../navigation/route-names.js';
+import {
+ AvatarSelectionRouteName,
+ ConnectEthereumRouteName,
+} from '../../navigation/route-names.js';
+import { useStyles } from '../../themes/colors.js';
+import Alert from '../../utils/alert.js';
+import AuthButtonContainer from '../auth-components/auth-button-container.react.js';
+import AuthContainer from '../auth-components/auth-container.react.js';
+import AuthContentContainer from '../auth-components/auth-content-container.react.js';
+
+export type ConnectFarcasterDCsParams = {
+ +userSelections: {
+ +coolOrNerdMode?: ?CoolOrNerdMode,
+ +keyserverURL?: ?string,
+ +farcasterID: string,
+ +farcasterAvatarURL: ?string,
+ },
+};
+
+type Props = {
+ +navigation: AuthNavigationProp<'ConnectFarcasterDCs'>,
+ +route: NavigationRoute<'ConnectFarcasterDCs'>,
+};
+
+function InnerConnectFarcasterDCs(props: Props): React.Node {
+ const { navigation, route } = props;
+
+ const { navigate } = navigation;
+ const userSelections = route.params?.userSelections;
+
+ const [mnemonic, setMnemonic] = React.useState<?string>(null);
+
+ const registrationContext = React.useContext(RegistrationContext);
+ invariant(registrationContext, 'registrationContext should be set');
+ const {
+ cachedSelections,
+ setCachedSelections,
+ skipEthereumLoginOnce,
+ setSkipEthereumLoginOnce,
+ } = registrationContext;
+
+ const { ethereumAccount } = cachedSelections;
+ const goToNextStep = React.useCallback(
+ (farcasterDCsToken?: ?string) => {
+ invariant(
+ !ethereumAccount || ethereumAccount.nonceTimestamp,
+ 'nonceTimestamp must be set after connecting to Ethereum account',
+ );
+ const nonceExpired =
+ ethereumAccount &&
+ ethereumAccount.nonceTimestamp &&
+ siweNonceExpired(ethereumAccount.nonceTimestamp);
+ if (nonceExpired) {
+ setCachedSelections(oldUserSelections => ({
+ ...oldUserSelections,
+ ethereumAccount: undefined,
+ }));
+ }
+
+ if (!skipEthereumLoginOnce || !ethereumAccount || nonceExpired) {
+ navigate<'ConnectEthereum'>({
+ name: ConnectEthereumRouteName,
+ params: {
+ userSelections: {
+ ...userSelections,
+ farcasterDCsToken,
+ },
+ },
+ });
+ return;
+ }
+
+ const newUserSelections = {
+ ...userSelections,
+ accountSelection: ethereumAccount,
+ farcasterDCsToken,
+ };
+ setSkipEthereumLoginOnce(false);
+ navigate<'AvatarSelection'>({
+ name: AvatarSelectionRouteName,
+ params: { userSelections: newUserSelections },
+ });
+ },
+ [
+ ethereumAccount,
+ navigate,
+ setCachedSelections,
+ setSkipEthereumLoginOnce,
+ skipEthereumLoginOnce,
+ userSelections,
+ ],
+ );
+
+ const onSkip = React.useCallback(() => {
+ if (cachedSelections.farcasterDCsToken) {
+ setCachedSelections(({ farcasterDCsToken, ...rest }) => rest);
+ }
+ goToNextStep();
+ }, [cachedSelections.farcasterDCsToken, goToNextStep, setCachedSelections]);
+
+ const getAuthToken = useGetAuthToken();
+ const [signingInProgress, setSigningInProgress] = React.useState(false);
+ const onConnect = React.useCallback(async () => {
+ if (!mnemonic) {
+ goToNextStep();
+ return;
+ }
+
+ setSigningInProgress(true);
+ try {
+ const token = await getAuthToken(userSelections.farcasterID, mnemonic);
+ setCachedSelections(oldUserSelections => ({
+ farcasterDCsToken: token,
+ ...oldUserSelections,
+ }));
+ goToNextStep(token);
+ } catch (e) {
+ Alert.alert(
+ 'Failed to connect',
+ 'Failed to connect to Farcaster Direct Casts. Please try again later.',
+ );
+ }
+ setSigningInProgress(false);
+ }, [
+ getAuthToken,
+ goToNextStep,
+ mnemonic,
+ setCachedSelections,
+ userSelections.farcasterID,
+ ]);
+
+ let buttonVariant = 'enabled';
+ if (!mnemonic || cachedSelections.farcasterDCsToken) {
+ buttonVariant = 'disabled';
+ } else if (signingInProgress) {
+ buttonVariant = 'loading';
+ }
+
+ const onUseAlreadyConnectedAccount = React.useCallback(() => {
+ goToNextStep(cachedSelections.farcasterDCsToken);
+ }, [cachedSelections.farcasterDCsToken, goToNextStep]);
+ const alreadyConnected = !!cachedSelections.farcasterDCsToken;
+ let alreadyConnectedButton = null;
+ if (alreadyConnected) {
+ alreadyConnectedButton = (
+ <PrimaryButton
+ onPress={onUseAlreadyConnectedAccount}
+ label="Use connected account"
+ variant="enabled"
+ />
+ );
+ }
+
+ const onChangeText = React.useCallback(
+ (text: string) => {
+ setMnemonic(text);
+ setCachedSelections(({ farcasterDCsToken, ...rest }) => rest);
+ },
+ [setCachedSelections],
+ );
+
+ const styles = useStyles(unboundStyles);
+ return React.useMemo(
+ () => (
+ <AuthContainer>
+ <AuthContentContainer style={styles.scrollViewContentContainer}>
+ <FarcasterPrompt textType="connect_DC" />
+ <RegistrationTextInput
+ autoCapitalize="none"
+ autoComplete="off"
+ autoCorrect={false}
+ editable={!signingInProgress}
+ keyboardType="default"
+ onChangeText={onChangeText}
+ onSubmitEditing={onConnect}
+ placeholder="Wallet mnemonic"
+ returnKeyType="go"
+ secureTextEntry={true}
+ value={mnemonic}
+ />
+ </AuthContentContainer>
+ <AuthButtonContainer>
+ {alreadyConnectedButton}
+ <PrimaryButton
+ onPress={onConnect}
+ label="Connect Direct Casts"
+ variant={buttonVariant}
+ />
+ <PrimaryButton
+ onPress={onSkip}
+ label="Do not connect"
+ variant="outline"
+ />
+ </AuthButtonContainer>
+ </AuthContainer>
+ ),
+ [
+ alreadyConnectedButton,
+ buttonVariant,
+ mnemonic,
+ onChangeText,
+ onConnect,
+ onSkip,
+ signingInProgress,
+ styles.scrollViewContentContainer,
+ ],
+ );
+}
+
+const unboundStyles = {
+ scrollViewContentContainer: {
+ flexGrow: 1,
+ },
+ description: {
+ fontFamily: 'Arial',
+ fontSize: 15,
+ lineHeight: 20,
+ color: 'panelForegroundSecondaryLabel',
+ paddingBottom: 16,
+ },
+};
+
+function ConnectFarcasterDCs(props: Props): React.Node {
+ return (
+ <FarcasterAuthContextProvider>
+ <InnerConnectFarcasterDCs {...props} />
+ </FarcasterAuthContextProvider>
+ );
+}
+
+export { ConnectFarcasterDCs };
diff --git a/native/account/registration/connect-farcaster.react.js b/native/account/registration/connect-farcaster.react.js
--- a/native/account/registration/connect-farcaster.react.js
+++ b/native/account/registration/connect-farcaster.react.js
@@ -7,6 +7,7 @@
import { IdentityClientContext } from 'lib/shared/identity-client-context.js';
import { useIsAppForegrounded } from 'lib/shared/lifecycle-utils.js';
import type { BaseFCAvatarInfo } from 'lib/utils/farcaster-helpers.js';
+import { supportsFarcasterDCs } from 'lib/utils/services-utils.js';
import type { AuthNavigationProp } from './auth-navigator.react.js';
import { siweNonceExpired } from './ethereum-utils.js';
@@ -64,6 +65,21 @@
const goToNextStep = React.useCallback(
(fid?: ?string, farcasterAvatarURL: ?string) => {
setWebViewState('closed');
+
+ if (fid && supportsFarcasterDCs) {
+ navigate<'ConnectFarcasterDCs'>({
+ name: 'ConnectFarcasterDCs',
+ params: {
+ userSelections: {
+ ...userSelections,
+ farcasterID: fid,
+ farcasterAvatarURL: farcasterAvatarURL,
+ },
+ },
+ });
+ return;
+ }
+
invariant(
!ethereumAccount || ethereumAccount.nonceTimestamp,
'nonceTimestamp must be set after connecting to Ethereum account',
@@ -87,6 +103,7 @@
...userSelections,
farcasterID: fid,
farcasterAvatarURL: farcasterAvatarURL,
+ farcasterDCsToken: null,
},
},
});
@@ -98,6 +115,7 @@
farcasterID: fid,
accountSelection: ethereumAccount,
farcasterAvatarURL: farcasterAvatarURL,
+ farcasterDCsToken: null,
};
setSkipEthereumLoginOnce(false);
navigate<'AvatarSelection'>({
@@ -116,14 +134,20 @@
);
const onSkip = React.useCallback(() => {
- if (cachedSelections.farcasterID || cachedSelections.farcasterAvatarURL) {
+ if (
+ cachedSelections.farcasterID ||
+ cachedSelections.farcasterAvatarURL ||
+ cachedSelections.farcasterDCsToken
+ ) {
setCachedSelections(
- ({ farcasterID, farcasterAvatarURL, ...rest }) => rest,
+ ({ farcasterID, farcasterAvatarURL, farcasterDCsToken, ...rest }) =>
+ rest,
);
}
goToNextStep();
}, [
cachedSelections.farcasterAvatarURL,
+ cachedSelections.farcasterDCsToken,
cachedSelections.farcasterID,
goToNextStep,
setCachedSelections,
diff --git a/native/account/registration/password-selection.react.js b/native/account/registration/password-selection.react.js
--- a/native/account/registration/password-selection.react.js
+++ b/native/account/registration/password-selection.react.js
@@ -27,7 +27,8 @@
+keyserverURL?: ?string,
+farcasterID: ?string,
+username: string,
- farcasterAvatarURL: ?string,
+ +farcasterAvatarURL: ?string,
+ +farcasterDCsToken: ?string,
},
};
diff --git a/native/account/registration/registration-server-call.js b/native/account/registration/registration-server-call.js
--- a/native/account/registration/registration-server-call.js
+++ b/native/account/registration/registration-server-call.js
@@ -150,6 +150,7 @@
farcasterID: ?string,
onNonceExpired: () => mixed,
onAlertAcknowledged: ?() => mixed,
+ farcasterDCsToken: ?string,
) => {
try {
await identityWalletRegisterCall({
@@ -157,6 +158,7 @@
message: accountSelection.message,
signature: accountSelection.signature,
fid: farcasterID,
+ farcasterDCsToken,
});
} catch (e) {
const messageForException = getMessageForException(e);
@@ -203,6 +205,7 @@
clearCachedSelections,
onNonceExpired,
onAlertAcknowledged,
+ farcasterDCsToken,
} = input;
if (accountSelection.accountType === 'username') {
await identityRegisterUsernameAccount(
@@ -216,6 +219,7 @@
farcasterID,
onNonceExpired,
onAlertAcknowledged,
+ farcasterDCsToken,
);
}
if (passedKeyserverURL) {
diff --git a/native/account/registration/registration-terms.react.js b/native/account/registration/registration-terms.react.js
--- a/native/account/registration/registration-terms.react.js
+++ b/native/account/registration/registration-terms.react.js
@@ -32,6 +32,7 @@
+avatarData: ?AvatarData,
+siweBackupSecrets?: ?SignedMessage,
+farcasterAvatarURL: ?string,
+ +farcasterDCsToken: ?string,
},
};
@@ -63,8 +64,13 @@
const { navigation } = props;
const { reconnectEthereum } = navigation;
- const { coolOrNerdMode, keyserverURL, farcasterID, farcasterAvatarURL } =
- userSelections;
+ const {
+ coolOrNerdMode,
+ keyserverURL,
+ farcasterID,
+ farcasterAvatarURL,
+ farcasterDCsToken,
+ } = userSelections;
const navigateToConnectEthereum = React.useCallback(() => {
reconnectEthereum({
userSelections: {
@@ -72,6 +78,7 @@
keyserverURL,
farcasterID,
farcasterAvatarURL,
+ farcasterDCsToken,
},
});
}, [
@@ -80,6 +87,7 @@
keyserverURL,
farcasterID,
farcasterAvatarURL,
+ farcasterDCsToken,
]);
const onNonceExpired = React.useCallback(() => {
setCachedSelections(oldUserSelections => ({
diff --git a/native/account/registration/registration-types.js b/native/account/registration/registration-types.js
--- a/native/account/registration/registration-types.js
+++ b/native/account/registration/registration-types.js
@@ -48,6 +48,7 @@
+clearCachedSelections: () => void,
+onNonceExpired: () => mixed,
+onAlertAcknowledged?: () => mixed,
+ +farcasterDCsToken: ?string,
};
export type CachedUserSelections = {
@@ -60,6 +61,7 @@
+farcasterID?: string,
+siweBackupSecrets?: ?SignedMessage,
+farcasterAvatarURL?: ?string,
+ +farcasterDCsToken?: ?string,
};
export const ensAvatarSelection: AvatarData = {
diff --git a/native/account/registration/siwe-backup-message-creation.react.js b/native/account/registration/siwe-backup-message-creation.react.js
--- a/native/account/registration/siwe-backup-message-creation.react.js
+++ b/native/account/registration/siwe-backup-message-creation.react.js
@@ -141,6 +141,7 @@
+accountSelection: AccountSelection,
+avatarData: ?AvatarData,
+farcasterAvatarURL: ?string,
+ +farcasterDCsToken: ?string,
},
};
diff --git a/native/account/registration/username-selection.react.js b/native/account/registration/username-selection.react.js
--- a/native/account/registration/username-selection.react.js
+++ b/native/account/registration/username-selection.react.js
@@ -28,6 +28,7 @@
+keyserverURL?: ?string,
+farcasterID: ?string,
+farcasterAvatarURL: ?string,
+ +farcasterDCsToken: ?string,
},
};
diff --git a/native/account/siwe-hooks.js b/native/account/siwe-hooks.js
--- a/native/account/siwe-hooks.js
+++ b/native/account/siwe-hooks.js
@@ -13,12 +13,13 @@
const identityWalletRegister = useIdentityWalletRegister();
const dispatchActionPromise = useDispatchActionPromise();
return React.useCallback(
- async ({ address, message, signature, fid }) => {
+ async ({ address, message, signature, fid, farcasterDCsToken }) => {
const siwePromise = identityWalletRegister(
address,
message,
signature,
fid,
+ farcasterDCsToken,
);
void dispatchActionPromise(identityRegisterActionTypes, siwePromise);
diff --git a/native/components/farcaster-prompt.react.js b/native/components/farcaster-prompt.react.js
--- a/native/components/farcaster-prompt.react.js
+++ b/native/components/farcaster-prompt.react.js
@@ -1,58 +1,82 @@
// @flow
import * as React from 'react';
-import { View, Text } from 'react-native';
+import { Text, View } from 'react-native';
import { useStyles } from '../themes/colors.js';
import FarcasterLogo from '../vectors/farcaster-logo.react.js';
-type TextType = 'connect' | 'disconnect';
+type TextType = 'connect' | 'disconnect' | 'connect_DC';
type Props = {
+textType: TextType,
};
+const prompts = {
+ connect: {
+ headerText: 'Do you want to connect your Farcaster account?',
+ bodyTexts: [
+ 'Connecting your Farcaster account lets us bootstrap your social ' +
+ 'graph. We’ll also surface communities based on your Farcaster ' +
+ 'channels.',
+ ],
+ displayLogo: true,
+ },
+ disconnect: {
+ headerText: 'Disconnect from Farcaster',
+ bodyTexts: ['You can disconnect your Farcaster account at any time.'],
+ displayLogo: true,
+ },
+ connect_DC: {
+ headerText: 'Do you want to connect your Farcaster Direct Casts?',
+ bodyTexts: [
+ 'If you share your Farcaster custody mnemonic below, you’ll be able to ' +
+ 'send and receive Direct Cast messages using Comm.',
+ 'You can find it in the Farcaster app within Settings → Advanced → ' +
+ 'Show Farcaster recovery phrase.',
+ 'Your mnemonic phrase is only used locally and is not sent to our ' +
+ 'servers.',
+ ],
+ displayLogo: false,
+ },
+};
+
function FarcasterPrompt(props: Props): React.Node {
const { textType } = props;
- let headerText;
- if (textType === 'disconnect') {
- headerText = 'Disconnect from Farcaster';
- } else {
- headerText = 'Do you want to connect your Farcaster account?';
- }
+ const { headerText, bodyTexts, displayLogo } = prompts[textType];
- let bodyText;
- if (textType === 'disconnect') {
- bodyText = 'You can disconnect your Farcaster account at any time.';
- } else {
- bodyText =
- 'Connecting your Farcaster account lets us bootstrap your social ' +
- 'graph. We’ll also surface communities based on your Farcaster ' +
- 'channels.';
+ const styles = useStyles(unboundStyles);
+
+ let farcasterLogo = null;
+ if (displayLogo) {
+ farcasterLogo = (
+ <View style={styles.farcasterLogoContainer}>
+ <FarcasterLogo />
+ </View>
+ );
}
- const styles = useStyles(unboundStyles);
- const farcasterPrompt = React.useMemo(
+ const bodyText = React.useMemo(
+ () =>
+ bodyTexts.map((text, id) => (
+ <Text style={styles.body} key={id}>
+ {text}
+ </Text>
+ )),
+ [bodyTexts, styles.body],
+ );
+
+ return React.useMemo(
() => (
<>
<Text style={styles.header}>{headerText}</Text>
- <Text style={styles.body}>{bodyText}</Text>
- <View style={styles.farcasterLogoContainer}>
- <FarcasterLogo />
- </View>
+ {bodyText}
+ {farcasterLogo}
</>
),
- [
- bodyText,
- headerText,
- styles.body,
- styles.farcasterLogoContainer,
- styles.header,
- ],
+ [bodyText, farcasterLogo, headerText, styles.header],
);
-
- return farcasterPrompt;
}
const unboundStyles = {
diff --git a/native/farcaster-auth/farcaster-auth-utils.js b/native/farcaster-auth/farcaster-auth-utils.js
new file mode 100644
--- /dev/null
+++ b/native/farcaster-auth/farcaster-auth-utils.js
@@ -0,0 +1,41 @@
+// @flow
+
+import * as React from 'react';
+
+import { useSignFarcasterAuthMessage } from 'lib/components/farcaster-auth-context.js';
+
+function useGetAuthToken(): (
+ fid: string,
+ walletMnemonic: string,
+) => Promise<string> {
+ const signAuthMessage = useSignFarcasterAuthMessage();
+
+ return React.useCallback(
+ async (fid: string, walletMnemonic: string) => {
+ const nonceResponse = await fetch(
+ 'https://client.farcaster.xyz/v2/get-dc-nonce',
+ );
+ const nonceData = await nonceResponse.json();
+ const nonce = nonceData.result.nonce;
+
+ const signResult = await signAuthMessage({
+ nonce,
+ fid,
+ walletMnemonic,
+ });
+
+ const params = new URLSearchParams({
+ message: signResult.message,
+ signature: signResult.signature,
+ });
+ const tokenResponse = await fetch(
+ `https://client.farcaster.xyz/v2/get-dc-auth-token?${params.toString()}`,
+ );
+ const tokenData = await tokenResponse.json();
+ return tokenData.result.token;
+ },
+ [signAuthMessage],
+ );
+}
+
+export { useGetAuthToken };
diff --git a/native/navigation/route-names.js b/native/navigation/route-names.js
--- a/native/navigation/route-names.js
+++ b/native/navigation/route-names.js
@@ -8,6 +8,7 @@
import type { ConnectSecondaryDeviceParams } from '../account/qr-auth/connect-secondary-device.react.js';
import type { AvatarSelectionParams } from '../account/registration/avatar-selection.react.js';
import type { ConnectEthereumParams } from '../account/registration/connect-ethereum.react.js';
+import type { ConnectFarcasterDCsParams } from '../account/registration/connect-farcaster-dcs.react.js';
import type { ConnectFarcasterParams } from '../account/registration/connect-farcaster.react.js';
import type { EmojiAvatarSelectionParams } from '../account/registration/emoji-avatar-selection.react.js';
import type { ExistingEthereumAccountParams } from '../account/registration/existing-ethereum-account.react.js';
@@ -142,6 +143,7 @@
export const RestoreSIWEBackupRouteName = 'RestoreSIWEBackup';
export const ExistingEthereumAccountRouteName = 'ExistingEthereumAccount';
export const ConnectFarcasterRouteName = 'ConnectFarcaster';
+export const ConnectFarcasterDCsRouteName = 'ConnectFarcasterDCs';
export const UsernameSelectionRouteName = 'UsernameSelection';
export const CommunityCreationRouteName = 'CommunityCreation';
export const CommunityConfigurationRouteName = 'CommunityConfiguration';
@@ -327,6 +329,7 @@
+ConnectEthereum: ConnectEthereumParams,
+ExistingEthereumAccount: ExistingEthereumAccountParams,
+ConnectFarcaster: ConnectFarcasterParams,
+ +ConnectFarcasterDCs: ConnectFarcasterDCsParams,
+CreateSIWEBackupMessage: CreateSIWEBackupMessageParams,
+UsernameSelection: UsernameSelectionParams,
+PasswordSelection: PasswordSelectionParams,
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sun, Dec 7, 10:17 PM (18 h, 46 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
5846190
Default Alt Text
D14911.1765145835.diff (25 KB)
Attached To
Mode
D14911: [native] Connect Farcaster DCs during registration
Attached
Detach File
Event Timeline
Log In to Comment