Skip to content

Commit 84b51fb

Browse files
committed
feat(farcaster): init draft for supporting farcaster login
1 parent c73b22c commit 84b51fb

File tree

18 files changed

+629
-6
lines changed

18 files changed

+629
-6
lines changed

packages/farcaster/.fatherrc.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import { defineConfig } from 'father';
2+
3+
export default defineConfig({
4+
extends: '../../.fatherrc.base.ts',
5+
});

packages/farcaster/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
# TODO

packages/farcaster/package.json

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
{
2+
"name": "@ant-design/web3-farcaster",
3+
"version": "1.0.0",
4+
"main": "dist/lib/index.js",
5+
"module": "dist/esm/index.js",
6+
"typings": "dist/esm/index.d.ts",
7+
"exports": {
8+
"import": "./dist/esm/index.js",
9+
"require": "./dist/lib/index.js",
10+
"types": "./dist/esm/index.d.ts"
11+
},
12+
"sideEffects": false,
13+
"files": [
14+
"dist",
15+
"CHANGELOG.md",
16+
"README.md"
17+
],
18+
"keywords": [
19+
"ant",
20+
"component",
21+
"components",
22+
"design",
23+
"framework",
24+
"frontend",
25+
"react",
26+
"react-component",
27+
"ui",
28+
"web3",
29+
"farcaster"
30+
],
31+
"homepage": "https://web3.ant.design",
32+
"bugs": {
33+
"url": "https://github.com/ant-design/ant-design-web3/issues"
34+
},
35+
"repository": {
36+
"type": "git",
37+
"url": "https://github.com/ant-design/ant-design-web3"
38+
},
39+
"scripts": {
40+
"dev": "father dev",
41+
"build": "father build"
42+
},
43+
"dependencies": {
44+
"@farcaster/auth-client": "^0.1.1",
45+
"@farcaster/auth-kit": "^0.3.1"
46+
},
47+
"devDependencies": {
48+
"father": "^4.4.4",
49+
"typescript": "^5.4.5"
50+
},
51+
"publishConfig": {
52+
"registry": "https://registry.npmjs.org",
53+
"access": "public"
54+
},
55+
"browserslist": [
56+
"last 2 versions",
57+
"Firefox ESR",
58+
"> 1%",
59+
"ie >= 11"
60+
]
61+
}

packages/farcaster/src/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
export * from './provider';
2+
export { QRCode } from '@farcaster/auth-kit';
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import type { FC } from 'react';
2+
import { render } from '@testing-library/react';
3+
4+
type RenderResult = ReturnType<typeof render>;
5+
type RenderWithUtils = RenderResult & {
6+
selector: <T extends Element = Element>(selector: string) => T | null;
7+
selectors: <T extends Element = Element>(selector: string) => NodeListOf<T>;
8+
};
9+
type XRender = (Comp: FC, options?: Parameters<typeof render>[1]) => RenderWithUtils;
10+
11+
export const xrender: XRender = (Comp, options) => {
12+
const { baseElement, ...others } = render(<Comp />, options);
13+
return {
14+
baseElement,
15+
...others,
16+
selector: (selector) => baseElement.querySelector(selector),
17+
selectors: (selector) => baseElement.querySelectorAll(selector),
18+
};
19+
};
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
import React, { useCallback, useEffect } from 'react';
2+
import type { Provider } from '@farcaster/auth-client';
3+
import { AuthKitProvider, useSignIn, type UseSignInArgs } from '@farcaster/auth-kit';
4+
5+
import '@farcaster/auth-kit/styles.css';
6+
7+
// declares locally in '@farcaster/auth-kit', but it is not exported
8+
interface AuthKitConfig {
9+
relay?: string;
10+
domain?: string;
11+
siweUri?: string;
12+
rpcUrl?: string;
13+
redirectUrl?: string;
14+
version?: string;
15+
provider?: Provider;
16+
}
17+
18+
interface IFarcasterContext extends Partial<ReturnType<typeof useSignIn>> {
19+
farcasterSupported: boolean;
20+
farcasterLogin: () => void;
21+
}
22+
23+
const FarcasterContext = React.createContext<IFarcasterContext>({
24+
farcasterSupported: false,
25+
farcasterLogin: () => {},
26+
});
27+
28+
const FarcasterConfigProvider: React.FC<React.PropsWithChildren<UseSignInArgs>> = ({
29+
children,
30+
...signInArgs
31+
}) => {
32+
const signInState = useSignIn(signInArgs);
33+
const { isError, reconnect, signIn, channelToken, connect } = signInState;
34+
35+
const farcasterLogin = useCallback(() => {
36+
if (isError) {
37+
reconnect();
38+
}
39+
signIn();
40+
}, [isError, reconnect, signIn]);
41+
42+
useEffect(() => {
43+
if (!channelToken) {
44+
connect();
45+
}
46+
}, [channelToken, connect]);
47+
48+
return (
49+
<FarcasterContext.Provider value={{ farcasterSupported: true, farcasterLogin, ...signInState }}>
50+
{children}
51+
</FarcasterContext.Provider>
52+
);
53+
};
54+
55+
interface Web3FarcasterProviderProps extends UseSignInArgs {
56+
config?: AuthKitConfig;
57+
}
58+
59+
export const useFarcaster = () => {
60+
const farcaster = React.useContext(FarcasterContext);
61+
return farcaster;
62+
};
63+
64+
export const FarcasterWeb3ConfigProvider: React.FC<
65+
React.PropsWithChildren<Web3FarcasterProviderProps>
66+
> = ({ children, config = {}, ...signInArgs }) => {
67+
return (
68+
<AuthKitProvider config={config}>
69+
<FarcasterConfigProvider {...signInArgs}>{children}</FarcasterConfigProvider>
70+
</AuthKitProvider>
71+
);
72+
};

packages/farcaster/tsconfig.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"extends": "../../tsconfig.base.json",
3+
"include": ["src", "global.d.ts"]
4+
}

packages/web3/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
"@ant-design/web3-assets": "workspace:*",
4747
"@ant-design/web3-common": "workspace:*",
4848
"@ant-design/web3-icons": "workspace:*",
49+
"@ant-design/web3-farcaster": "workspace:*",
4950
"@ctrl/tinycolor": "^4.1.0",
5051
"@inline-svg-unique-id/react": "^1.2.3",
5152
"antd": "^5.17.3",
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import React from 'react';
2+
import { QRCode, useFarcaster } from '@ant-design/web3-farcaster';
3+
4+
import { connectModalContext } from '../context';
5+
import MainPanelHeader from './MainPanelHeader';
6+
7+
const FarcasterCard = () => {
8+
const { url, error, isError } = useFarcaster();
9+
const { prefixCls } = React.useContext(connectModalContext);
10+
11+
return (
12+
<>
13+
<div className={`${prefixCls}-qr-code-container`}>
14+
<MainPanelHeader title="Sign in with Farcaster" />
15+
<div className={`${prefixCls}-qr-code-box`}>
16+
{isError ? (
17+
<>
18+
<div>Error</div>
19+
<div>{error?.message ?? 'Unknown error, please try again.'}</div>
20+
</>
21+
) : url ? (
22+
<QRCode uri={url} size={300} logoSize={28} logoMargin={16} />
23+
) : null}
24+
</div>
25+
<div className={`${prefixCls}-qr-code-tips`}>
26+
<div>Scan with your phone&apos;s camera to continue.</div>
27+
</div>
28+
</div>
29+
</>
30+
);
31+
};
32+
33+
export default FarcasterCard;

packages/web3/src/connect-modal/components/MainPanel.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import React, { useContext } from 'react';
33
import { connectModalContext } from '../context';
44
import type { ConnectModalProps } from '../interface';
55
import DefaultGuidePanel from './DefaultGuidePanel';
6+
import FarcasterCard from './FarcasterCard';
67
import LinkPanel from './LinkPanel';
78
import QrCode from './QrCode';
89
import WalletCard from './WalletCard';
@@ -28,6 +29,7 @@ const MainPanel: React.FC<MainPanelProps> = (props) => {
2829
{panelRoute === 'downloadQrCode' && selectedWallet ? (
2930
<QrCode wallet={selectedWallet} simple={simple} download />
3031
) : null}
32+
{panelRoute === 'farcaster' ? <FarcasterCard /> : null}
3133
</div>
3234
);
3335
};

0 commit comments

Comments
 (0)