From 339e598c2ddea60af42f2e11de2e9fb9c9c450f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Kvasnic=CC=8Ca=CC=81k?= Date: Wed, 20 Nov 2024 14:42:15 +0100 Subject: [PATCH] feat: allow to override fetch function in farcaster identity hooks --- .changeset/serious-phones-judge.md | 5 +++ .../farcaster/use-farcaster-identity.tsx | 42 ++++++++++++------ .../use-farcaster-multi-identity.tsx | 43 ++++++++++++------- 3 files changed, 61 insertions(+), 29 deletions(-) create mode 100644 .changeset/serious-phones-judge.md diff --git a/.changeset/serious-phones-judge.md b/.changeset/serious-phones-judge.md new file mode 100644 index 000000000..dca0330f2 --- /dev/null +++ b/.changeset/serious-phones-judge.md @@ -0,0 +1,5 @@ +--- +"@frames.js/render": patch +--- + +feat(@frames.js/render): allow to override fetch function in farcaster identity hooks diff --git a/packages/render/src/identity/farcaster/use-farcaster-identity.tsx b/packages/render/src/identity/farcaster/use-farcaster-identity.tsx index db3d73b82..e8d7c27e2 100644 --- a/packages/render/src/identity/farcaster/use-farcaster-identity.tsx +++ b/packages/render/src/identity/farcaster/use-farcaster-identity.tsx @@ -134,7 +134,14 @@ type UseFarcasterIdentityOptions = { * @defaultValue 'farcasterIdentity' */ storageKey?: string; + /** + * Function used to generate a unique user id for signer._id property value + */ generateUserId?: () => string | number; + /** + * Custom fetch function used to do requests + */ + fetchFn?: typeof fetch; /** * Used to detect if the current context is visible, this affects the polling of the signer approval status. */ @@ -157,6 +164,8 @@ const defaultGenerateUserId = (): number => { return Date.now(); }; +const defaultFetchFn: typeof fetch = (...args) => fetch(...args); + export function useFarcasterIdentity({ onMissingIdentity, enableIdentityPolling = true, @@ -169,6 +178,7 @@ export function useFarcasterIdentity({ onLogInStart, onLogOut, generateUserId = defaultGenerateUserId, + fetchFn = defaultFetchFn, }: UseFarcasterIdentityOptions): FarcasterSignerInstance { const storageRef = useRef(storage); const identityPoller = useRef(new IdentityPoller()).current; @@ -194,13 +204,14 @@ export function useFarcasterIdentity({ const onLogOutRef = useFreshRef(onLogOut); const generateUserIdRef = useFreshRef(generateUserId); const onMissingIdentityRef = useFreshRef(onMissingIdentity); + const fetchFnRef = useFreshRef(fetchFn); const createFarcasterSigner = useCallback(async (): Promise => { try { const keypair = await createKeypairEDDSA(); const keypairString = convertKeypairToHex(keypair); - const authorizationResponse = await fetch( + const authorizationResponse = await fetchFnRef.current( // real signer or local one are handled by local route so we don't need to expose anything to client side bundle signerUrl, { @@ -231,18 +242,21 @@ export function useFarcasterIdentity({ const { result: { signedKeyRequest }, } = (await ( - await fetch(`https://api.warpcast.com/v2/signed-key-requests`, { - method: "POST", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify({ - key: keypairString.publicKey, - signature, - requestFid, - deadline, - }), - }) + await fetchFnRef.current( + "https://api.warpcast.com/v2/signed-key-requests", + { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + key: keypairString.publicKey, + signature, + requestFid, + deadline, + }), + } + ) ).json()) as { result: { signedKeyRequest: { token: string; deeplinkUrl: string }; @@ -297,7 +311,7 @@ export function useFarcasterIdentity({ console.error("@frames.js/render: API Call failed", error); throw error; } - }, [generateUserIdRef, onLogInStartRef, setState, signerUrl]); + }, [fetchFnRef, generateUserIdRef, onLogInStartRef, setState, signerUrl]); const impersonateUser = useCallback( async (fid: number) => { diff --git a/packages/render/src/identity/farcaster/use-farcaster-multi-identity.tsx b/packages/render/src/identity/farcaster/use-farcaster-multi-identity.tsx index b5142bbf2..f4e1eeb13 100644 --- a/packages/render/src/identity/farcaster/use-farcaster-multi-identity.tsx +++ b/packages/render/src/identity/farcaster/use-farcaster-multi-identity.tsx @@ -195,7 +195,14 @@ type UseFarcasterMultiIdentityOptions = { onLogOut?: (identity: FarcasterSigner) => void; onIdentityRemove?: (identity: FarcasterSigner) => void; onIdentitySelect?: (identity: FarcasterSigner) => void; + /** + * Function used to generate a unique user id for signer._id property value + */ generateUserId?: () => string | number; + /** + * Custom fetch function used to do requests + */ + fetchFn?: typeof fetch; }; export type FarcasterMultiSignerInstance = @@ -210,6 +217,7 @@ export type FarcasterMultiSignerInstance = const defaultStorage = new WebStorage(); const defaultGenerateUserId = (): number => Date.now(); +const defaultFetchFn: typeof fetch = (...args) => fetch(...args); type SignedKeyRequestSponsorship = { sponsorFid: number; @@ -229,6 +237,7 @@ export function useFarcasterMultiIdentity({ onIdentityRemove, onIdentitySelect, generateUserId = defaultGenerateUserId, + fetchFn = defaultFetchFn, }: UseFarcasterMultiIdentityOptions): FarcasterMultiSignerInstance { const storageRef = useRef(storage); const identityPoller = useRef(new IdentityPoller()).current; @@ -268,13 +277,14 @@ export function useFarcasterMultiIdentity({ const onIdentitySelectRef = useFreshRef(onIdentitySelect); const generateUserIdRef = useFreshRef(generateUserId); const onMissingIdentityRef = useFreshRef(onMissingIdentity); + const fetchFnRef = useFreshRef(fetchFn); const createFarcasterSigner = useCallback(async (): Promise => { try { const keypair = await createKeypairEDDSA(); const keypairString = convertKeypairToHex(keypair); - const authorizationResponse = await fetch( + const authorizationResponse = await fetchFnRef.current( // real signer or local one are handled by local route so we don't need to expose anything to client side bundle signerUrl, { @@ -312,19 +322,22 @@ export function useFarcasterMultiIdentity({ const { result: { signedKeyRequest }, } = (await ( - await fetch(`https://api.warpcast.com/v2/signed-key-requests`, { - method: "POST", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify({ - key: keypairString.publicKey, - signature, - requestFid, - deadline, - sponsorship, - }), - }) + await fetchFnRef.current( + "https://api.warpcast.com/v2/signed-key-requests", + { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + key: keypairString.publicKey, + signature, + requestFid, + deadline, + sponsorship, + }), + } + ) ).json()) as { result: { signedKeyRequest: { @@ -383,7 +396,7 @@ export function useFarcasterMultiIdentity({ console.error("@frames.js/render: API Call failed", error); throw error; } - }, [generateUserIdRef, onLogInStartRef, setState, signerUrl]); + }, [fetchFnRef, generateUserIdRef, onLogInStartRef, setState, signerUrl]); const impersonateUser = useCallback( async (fid: number) => {