mirror of
https://github.com/neynarxyz/create-farcaster-mini-app.git
synced 2025-12-07 09:52:31 -05:00
Correct formating imports
This commit is contained in:
@@ -11,14 +11,14 @@ export async function GET(request: Request) {
|
||||
error:
|
||||
'Neynar API key is not configured. Please add NEYNAR_API_KEY to your environment variables.',
|
||||
},
|
||||
{ status: 500 }
|
||||
{ status: 500 },
|
||||
);
|
||||
}
|
||||
|
||||
if (!fid) {
|
||||
return NextResponse.json(
|
||||
{ error: 'FID parameter is required' },
|
||||
{ status: 400 }
|
||||
{ status: 400 },
|
||||
);
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ export async function GET(request: Request) {
|
||||
headers: {
|
||||
'x-api-key': apiKey,
|
||||
},
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
if (!response.ok) {
|
||||
@@ -48,7 +48,7 @@ export async function GET(request: Request) {
|
||||
error:
|
||||
'Failed to fetch best friends. Please check your Neynar API key and try again.',
|
||||
},
|
||||
{ status: 500 }
|
||||
{ status: 500 },
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,6 +33,6 @@ export async function GET(request: NextRequest) {
|
||||
{
|
||||
width: 1200,
|
||||
height: 800,
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { notificationDetailsSchema } from '@farcaster/frame-sdk';
|
||||
import { NextRequest } from 'next/server';
|
||||
import { notificationDetailsSchema } from '@farcaster/frame-sdk';
|
||||
import { z } from 'zod';
|
||||
import { setUserNotificationDetails } from '~/lib/kv';
|
||||
import { sendMiniAppNotification } from '~/lib/notifs';
|
||||
import { sendNeynarMiniAppNotification } from '~/lib/neynar';
|
||||
import { sendMiniAppNotification } from '~/lib/notifs';
|
||||
|
||||
const requestSchema = z.object({
|
||||
fid: z.number(),
|
||||
@@ -22,7 +22,7 @@ export async function POST(request: NextRequest) {
|
||||
if (requestBody.success === false) {
|
||||
return Response.json(
|
||||
{ success: false, errors: requestBody.error.errors },
|
||||
{ status: 400 }
|
||||
{ status: 400 },
|
||||
);
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ export async function POST(request: NextRequest) {
|
||||
if (!neynarEnabled) {
|
||||
await setUserNotificationDetails(
|
||||
Number(requestBody.data.fid),
|
||||
requestBody.data.notificationDetails
|
||||
requestBody.data.notificationDetails,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -47,12 +47,12 @@ export async function POST(request: NextRequest) {
|
||||
if (sendResult.state === 'error') {
|
||||
return Response.json(
|
||||
{ success: false, error: sendResult.error },
|
||||
{ status: 500 }
|
||||
{ status: 500 },
|
||||
);
|
||||
} else if (sendResult.state === 'rate_limit') {
|
||||
return Response.json(
|
||||
{ success: false, error: 'Rate limited' },
|
||||
{ status: 429 }
|
||||
{ status: 429 },
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { NeynarAPIClient } from '@neynar/nodejs-sdk';
|
||||
import { NextResponse } from 'next/server';
|
||||
import { NeynarAPIClient } from '@neynar/nodejs-sdk';
|
||||
|
||||
export async function GET(request: Request) {
|
||||
const apiKey = process.env.NEYNAR_API_KEY;
|
||||
@@ -12,14 +12,14 @@ export async function GET(request: Request) {
|
||||
error:
|
||||
'Neynar API key is not configured. Please add NEYNAR_API_KEY to your environment variables.',
|
||||
},
|
||||
{ status: 500 }
|
||||
{ status: 500 },
|
||||
);
|
||||
}
|
||||
|
||||
if (!fids) {
|
||||
return NextResponse.json(
|
||||
{ error: 'FIDs parameter is required' },
|
||||
{ status: 400 }
|
||||
{ status: 400 },
|
||||
);
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@ export async function GET(request: Request) {
|
||||
error:
|
||||
'Failed to fetch users. Please check your Neynar API key and try again.',
|
||||
},
|
||||
{ status: 500 }
|
||||
{ status: 500 },
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { NextRequest } from 'next/server';
|
||||
import {
|
||||
ParseWebhookEvent,
|
||||
parseWebhookEvent,
|
||||
verifyAppKeyWithNeynar,
|
||||
} from '@farcaster/frame-node';
|
||||
import { NextRequest } from 'next/server';
|
||||
import { APP_NAME } from '~/lib/constants';
|
||||
import {
|
||||
deleteUserNotificationDetails,
|
||||
@@ -34,19 +34,19 @@ export async function POST(request: NextRequest) {
|
||||
// The request data is invalid
|
||||
return Response.json(
|
||||
{ success: false, error: error.message },
|
||||
{ status: 400 }
|
||||
{ status: 400 },
|
||||
);
|
||||
case 'VerifyJsonFarcasterSignature.InvalidAppKeyError':
|
||||
// The app key is invalid
|
||||
return Response.json(
|
||||
{ success: false, error: error.message },
|
||||
{ status: 401 }
|
||||
{ status: 401 },
|
||||
);
|
||||
case 'VerifyJsonFarcasterSignature.VerifyAppKeyError':
|
||||
// Internal error verifying the app key (caller may want to try again)
|
||||
return Response.json(
|
||||
{ success: false, error: error.message },
|
||||
{ status: 500 }
|
||||
{ status: 500 },
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ const AppComponent = dynamic(() => import('~/components/App'), {
|
||||
});
|
||||
|
||||
export default function App(
|
||||
{ title }: { title?: string } = { title: APP_NAME }
|
||||
{ title }: { title?: string } = { title: APP_NAME },
|
||||
) {
|
||||
return <AppComponent title={title} />;
|
||||
}
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import type { Metadata } from 'next';
|
||||
|
||||
import { getSession } from '~/auth';
|
||||
import '~/app/globals.css';
|
||||
import { Providers } from '~/app/providers';
|
||||
import { getSession } from '~/auth';
|
||||
import { APP_NAME, APP_DESCRIPTION } from '~/lib/constants';
|
||||
|
||||
export const metadata: Metadata = {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Metadata } from 'next';
|
||||
import App from './app';
|
||||
import { APP_NAME, APP_DESCRIPTION, APP_OG_IMAGE_URL } from '~/lib/constants';
|
||||
import { getMiniAppEmbedMetadata } from '~/lib/utils';
|
||||
import App from './app';
|
||||
|
||||
export const revalidate = 300;
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
'use client';
|
||||
|
||||
import dynamic from 'next/dynamic';
|
||||
import { MiniAppProvider } from '@neynar/react';
|
||||
import type { Session } from 'next-auth';
|
||||
import { SessionProvider } from 'next-auth/react';
|
||||
import { MiniAppProvider } from '@neynar/react';
|
||||
import { SafeFarcasterSolanaProvider } from '~/components/providers/SafeFarcasterSolanaProvider';
|
||||
import { ANALYTICS_ENABLED } from '~/lib/constants';
|
||||
|
||||
@@ -11,7 +11,7 @@ const WagmiProvider = dynamic(
|
||||
() => import('~/components/providers/WagmiProvider'),
|
||||
{
|
||||
ssr: false,
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
export function Providers({
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { Metadata } from 'next';
|
||||
import { redirect } from 'next/navigation';
|
||||
import type { Metadata } from 'next';
|
||||
import { APP_URL, APP_NAME, APP_DESCRIPTION } from '~/lib/constants';
|
||||
import { getMiniAppEmbedMetadata } from '~/lib/utils';
|
||||
export const revalidate = 300;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { createAppClient, viemConnector } from '@farcaster/auth-client';
|
||||
import { AuthOptions, getServerSession } from 'next-auth';
|
||||
import CredentialsProvider from 'next-auth/providers/credentials';
|
||||
import { createAppClient, viemConnector } from '@farcaster/auth-client';
|
||||
|
||||
declare module 'next-auth' {
|
||||
interface Session {
|
||||
@@ -97,7 +97,7 @@ export const authOptions: AuthOptions = {
|
||||
},
|
||||
cookies: {
|
||||
sessionToken: {
|
||||
name: `next-auth.session-token`,
|
||||
name: 'next-auth.session-token',
|
||||
options: {
|
||||
httpOnly: true,
|
||||
sameSite: 'none',
|
||||
@@ -106,7 +106,7 @@ export const authOptions: AuthOptions = {
|
||||
},
|
||||
},
|
||||
callbackUrl: {
|
||||
name: `next-auth.callback-url`,
|
||||
name: 'next-auth.callback-url',
|
||||
options: {
|
||||
sameSite: 'none',
|
||||
path: '/',
|
||||
@@ -114,7 +114,7 @@ export const authOptions: AuthOptions = {
|
||||
},
|
||||
},
|
||||
csrfToken: {
|
||||
name: `next-auth.csrf-token`,
|
||||
name: 'next-auth.csrf-token',
|
||||
options: {
|
||||
httpOnly: true,
|
||||
sameSite: 'none',
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
import { useEffect } from 'react';
|
||||
import { useMiniApp } from '@neynar/react';
|
||||
import { Header } from '~/components/ui/Header';
|
||||
import { Footer } from '~/components/ui/Footer';
|
||||
import { Header } from '~/components/ui/Header';
|
||||
import {
|
||||
HomeTab,
|
||||
ActionsTab,
|
||||
@@ -55,7 +55,7 @@ export interface AppProps {
|
||||
* ```
|
||||
*/
|
||||
export default function App(
|
||||
{ title }: AppProps = { title: 'Neynar Starter Kit' }
|
||||
{ title }: AppProps = { title: 'Neynar Starter Kit' },
|
||||
) {
|
||||
// --- Hooks ---
|
||||
const { isSDKLoaded, context, setInitialTab, setActiveTab, currentTab } =
|
||||
|
||||
@@ -5,9 +5,9 @@ import { sdk } from '@farcaster/frame-sdk';
|
||||
const FarcasterSolanaProvider = dynamic(
|
||||
() =>
|
||||
import('@farcaster/mini-app-solana').then(
|
||||
mod => mod.FarcasterSolanaProvider
|
||||
mod => mod.FarcasterSolanaProvider,
|
||||
),
|
||||
{ ssr: false }
|
||||
{ ssr: false },
|
||||
);
|
||||
|
||||
type SafeFarcasterSolanaProviderProps = {
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import { createConfig, http, WagmiProvider } from 'wagmi';
|
||||
import { base, degen, mainnet, optimism, unichain, celo } from 'wagmi/chains';
|
||||
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
|
||||
import { useEffect, useState } from 'react';
|
||||
import React from 'react';
|
||||
import { farcasterFrame } from '@farcaster/frame-wagmi-connector';
|
||||
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
|
||||
import { createConfig, http, WagmiProvider } from 'wagmi';
|
||||
import { useConnect, useAccount } from 'wagmi';
|
||||
import { base, degen, mainnet, optimism, unichain, celo } from 'wagmi/chains';
|
||||
import { coinbaseWallet, metaMask } from 'wagmi/connectors';
|
||||
import { APP_NAME, APP_ICON_URL, APP_URL } from '~/lib/constants';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { useConnect, useAccount } from 'wagmi';
|
||||
import React from 'react';
|
||||
|
||||
// Custom hook for Coinbase Wallet detection and auto-connection
|
||||
function useCoinbaseWalletAutoConnect() {
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
'use client';
|
||||
|
||||
import { useState } from 'react';
|
||||
import { APP_NAME } from '~/lib/constants';
|
||||
import sdk from '@farcaster/frame-sdk';
|
||||
import { useMiniApp } from '@neynar/react';
|
||||
import { APP_NAME } from '~/lib/constants';
|
||||
|
||||
type HeaderProps = {
|
||||
neynarUser?: {
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
'use client';
|
||||
|
||||
import { useCallback, useState, useEffect } from 'react';
|
||||
import { Button } from './Button';
|
||||
import { useMiniApp } from '@neynar/react';
|
||||
import { type ComposeCast } from '@farcaster/frame-sdk';
|
||||
import { useMiniApp } from '@neynar/react';
|
||||
import { Button } from './Button';
|
||||
|
||||
interface EmbedConfig {
|
||||
path?: string;
|
||||
@@ -86,7 +86,7 @@ export function ShareButton({
|
||||
// Add UTM parameters
|
||||
url.searchParams.set(
|
||||
'utm_source',
|
||||
`share-cast-${context?.user?.fid || 'unknown'}`
|
||||
`share-cast-${context?.user?.fid || 'unknown'}`,
|
||||
);
|
||||
|
||||
// If custom image generator is provided, use it
|
||||
@@ -98,7 +98,7 @@ export function ShareButton({
|
||||
return url.toString();
|
||||
}
|
||||
return embed.url || '';
|
||||
})
|
||||
}),
|
||||
);
|
||||
|
||||
// Open cast composer with all supported intents
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import * as React from 'react';
|
||||
|
||||
import { cn } from '~/lib/utils';
|
||||
|
||||
const Input = React.forwardRef<HTMLInputElement, React.ComponentProps<'input'>>(
|
||||
@@ -9,13 +8,13 @@ const Input = React.forwardRef<HTMLInputElement, React.ComponentProps<'input'>>(
|
||||
type={type}
|
||||
className={cn(
|
||||
'flex h-10 w-full rounded-md border border-neutral-200 bg-white px-3 py-2 text-base ring-offset-white file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-neutral-950 placeholder:text-neutral-500 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-neutral-950 focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 md:text-sm dark:border-neutral-800 dark:bg-neutral-950 dark:ring-offset-neutral-950 dark:file:text-neutral-50 dark:placeholder:text-neutral-400 dark:focus-visible:ring-neutral-300',
|
||||
className
|
||||
className,
|
||||
)}
|
||||
ref={ref}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
Input.displayName = 'Input';
|
||||
|
||||
|
||||
@@ -3,11 +3,10 @@
|
||||
import * as React from 'react';
|
||||
import * as LabelPrimitive from '@radix-ui/react-label';
|
||||
import { cva, type VariantProps } from 'class-variance-authority';
|
||||
|
||||
import { cn } from '~/lib/utils';
|
||||
|
||||
const labelVariants = cva(
|
||||
'text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70'
|
||||
'text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70',
|
||||
);
|
||||
|
||||
const Label = React.forwardRef<
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
'use client';
|
||||
|
||||
import { useCallback, useState } from 'react';
|
||||
import { useMiniApp } from '@neynar/react';
|
||||
import { ShareButton } from '../Share';
|
||||
import { Button } from '../Button';
|
||||
import { SignIn } from '../wallet/SignIn';
|
||||
import { type Haptics } from '@farcaster/frame-sdk';
|
||||
import { useMiniApp } from '@neynar/react';
|
||||
import { Button } from '../Button';
|
||||
import { ShareButton } from '../Share';
|
||||
import { SignIn } from '../wallet/SignIn';
|
||||
|
||||
/**
|
||||
* ActionsTab component handles mini app actions like sharing, notifications, and haptic feedback.
|
||||
@@ -98,7 +98,7 @@ export function ActionsTab() {
|
||||
setTimeout(
|
||||
() =>
|
||||
setNotificationState(prev => ({ ...prev, shareUrlCopied: false })),
|
||||
2000
|
||||
2000,
|
||||
);
|
||||
}
|
||||
}, [context?.user?.fid]);
|
||||
@@ -182,7 +182,7 @@ export function ActionsTab() {
|
||||
value={selectedHapticIntensity}
|
||||
onChange={e =>
|
||||
setSelectedHapticIntensity(
|
||||
e.target.value as Haptics.ImpactOccurredType
|
||||
e.target.value as Haptics.ImpactOccurredType,
|
||||
)
|
||||
}
|
||||
className="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100 focus:outline-none focus:ring-2 focus:ring-primary"
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
'use client';
|
||||
|
||||
import { useCallback, useMemo, useState, useEffect } from 'react';
|
||||
import { useMiniApp } from '@neynar/react';
|
||||
import { useWallet as useSolanaWallet } from '@solana/wallet-adapter-react';
|
||||
import {
|
||||
useAccount,
|
||||
useSendTransaction,
|
||||
@@ -12,17 +14,15 @@ import {
|
||||
useChainId,
|
||||
type Connector,
|
||||
} from 'wagmi';
|
||||
import { useWallet as useSolanaWallet } from '@solana/wallet-adapter-react';
|
||||
import { base, degen, mainnet, optimism, unichain } from 'wagmi/chains';
|
||||
import { Button } from '../Button';
|
||||
import { truncateAddress } from '../../../lib/truncateAddress';
|
||||
import { renderError } from '../../../lib/errorUtils';
|
||||
import { SignEvmMessage } from '../wallet/SignEvmMessage';
|
||||
import { SendEth } from '../wallet/SendEth';
|
||||
import { SignSolanaMessage } from '../wallet/SignSolanaMessage';
|
||||
import { SendSolana } from '../wallet/SendSolana';
|
||||
import { USE_WALLET, APP_NAME } from '../../../lib/constants';
|
||||
import { useMiniApp } from '@neynar/react';
|
||||
import { renderError } from '../../../lib/errorUtils';
|
||||
import { truncateAddress } from '../../../lib/truncateAddress';
|
||||
import { Button } from '../Button';
|
||||
import { SendEth } from '../wallet/SendEth';
|
||||
import { SendSolana } from '../wallet/SendSolana';
|
||||
import { SignEvmMessage } from '../wallet/SignEvmMessage';
|
||||
import { SignSolanaMessage } from '../wallet/SignSolanaMessage';
|
||||
|
||||
/**
|
||||
* WalletTab component manages wallet-related UI for both EVM and Solana chains.
|
||||
@@ -112,7 +112,7 @@ function ConnectionControls({
|
||||
console.log('Manual Farcaster connection attempt');
|
||||
console.log(
|
||||
'Connectors:',
|
||||
connectors.map((c, i) => `${i}: ${c.name}`)
|
||||
connectors.map((c, i) => `${i}: ${c.name}`),
|
||||
);
|
||||
connect({ connector: connectors[0] });
|
||||
}}
|
||||
@@ -213,7 +213,7 @@ export function WalletTab() {
|
||||
console.log('- User FID:', context.user.fid);
|
||||
console.log(
|
||||
'- Available connectors:',
|
||||
connectors.map((c, i) => `${i}: ${c.name}`)
|
||||
connectors.map((c, i) => `${i}: ${c.name}`),
|
||||
);
|
||||
console.log('- Using connector:', connectors[0].name);
|
||||
console.log('- In Farcaster client:', isInFarcasterClient);
|
||||
@@ -278,7 +278,7 @@ export function WalletTab() {
|
||||
onSuccess: hash => {
|
||||
setEvmContractTransactionHash(hash);
|
||||
},
|
||||
}
|
||||
},
|
||||
);
|
||||
}, [sendTransaction]);
|
||||
|
||||
|
||||
@@ -7,9 +7,9 @@ import {
|
||||
useWaitForTransactionReceipt,
|
||||
} from 'wagmi';
|
||||
import { base } from 'wagmi/chains';
|
||||
import { Button } from '../Button';
|
||||
import { truncateAddress } from '../../../lib/truncateAddress';
|
||||
import { renderError } from '../../../lib/errorUtils';
|
||||
import { truncateAddress } from '../../../lib/truncateAddress';
|
||||
import { Button } from '../Button';
|
||||
|
||||
/**
|
||||
* SendEth component handles sending ETH transactions to protocol guild addresses.
|
||||
|
||||
@@ -6,9 +6,9 @@ import {
|
||||
useWallet as useSolanaWallet,
|
||||
} from '@solana/wallet-adapter-react';
|
||||
import { PublicKey, SystemProgram, Transaction } from '@solana/web3.js';
|
||||
import { Button } from '../Button';
|
||||
import { truncateAddress } from '../../../lib/truncateAddress';
|
||||
import { renderError } from '../../../lib/errorUtils';
|
||||
import { truncateAddress } from '../../../lib/truncateAddress';
|
||||
import { Button } from '../Button';
|
||||
|
||||
/**
|
||||
* SendSolana component handles sending SOL transactions on Solana.
|
||||
@@ -71,7 +71,7 @@ export function SendSolana() {
|
||||
fromPubkey: new PublicKey(fromPubkeyStr),
|
||||
toPubkey: new PublicKey(toPubkeyStr),
|
||||
lamports: 0n,
|
||||
})
|
||||
}),
|
||||
);
|
||||
transaction.recentBlockhash = blockhash;
|
||||
transaction.feePayer = new PublicKey(fromPubkeyStr);
|
||||
|
||||
@@ -3,10 +3,10 @@
|
||||
import { useCallback } from 'react';
|
||||
import { useAccount, useConnect, useSignMessage } from 'wagmi';
|
||||
import { base } from 'wagmi/chains';
|
||||
import { Button } from '../Button';
|
||||
import { config } from '../../providers/WagmiProvider';
|
||||
import { APP_NAME } from '../../../lib/constants';
|
||||
import { renderError } from '../../../lib/errorUtils';
|
||||
import { config } from '../../providers/WagmiProvider';
|
||||
import { Button } from '../Button';
|
||||
|
||||
/**
|
||||
* SignEvmMessage component handles signing messages on EVM-compatible chains.
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
'use client';
|
||||
|
||||
import { useCallback, useState } from 'react';
|
||||
import { signIn, signOut, getCsrfToken } from 'next-auth/react';
|
||||
import sdk, { SignIn as SignInCore } from '@farcaster/frame-sdk';
|
||||
import { signIn, signOut, getCsrfToken } from 'next-auth/react';
|
||||
import { useSession } from 'next-auth/react';
|
||||
import { Button } from '../Button';
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
'use client';
|
||||
|
||||
import { useCallback, useState } from 'react';
|
||||
import { Button } from '../Button';
|
||||
import { renderError } from '../../../lib/errorUtils';
|
||||
import { Button } from '../Button';
|
||||
|
||||
interface SignSolanaMessageProps {
|
||||
signMessage?: (message: Uint8Array) => Promise<Uint8Array>;
|
||||
|
||||
@@ -31,7 +31,7 @@ export function renderError(error: unknown): ReactElement | null {
|
||||
// Special handling for user rejections in wallet operations
|
||||
if (error instanceof BaseError) {
|
||||
const isUserRejection = error.walk(
|
||||
e => e instanceof UserRejectedRequestError
|
||||
e => e instanceof UserRejectedRequestError,
|
||||
);
|
||||
|
||||
if (isUserRejection) {
|
||||
|
||||
@@ -19,7 +19,7 @@ function getUserNotificationDetailsKey(fid: number): string {
|
||||
}
|
||||
|
||||
export async function getUserNotificationDetails(
|
||||
fid: number
|
||||
fid: number,
|
||||
): Promise<FrameNotificationDetails | null> {
|
||||
const key = getUserNotificationDetailsKey(fid);
|
||||
if (redis) {
|
||||
@@ -30,7 +30,7 @@ export async function getUserNotificationDetails(
|
||||
|
||||
export async function setUserNotificationDetails(
|
||||
fid: number,
|
||||
notificationDetails: FrameNotificationDetails
|
||||
notificationDetails: FrameNotificationDetails,
|
||||
): Promise<void> {
|
||||
const key = getUserNotificationDetailsKey(fid);
|
||||
if (redis) {
|
||||
@@ -41,7 +41,7 @@ export async function setUserNotificationDetails(
|
||||
}
|
||||
|
||||
export async function deleteUserNotificationDetails(
|
||||
fid: number
|
||||
fid: number,
|
||||
): Promise<void> {
|
||||
const key = getUserNotificationDetailsKey(fid);
|
||||
if (redis) {
|
||||
|
||||
@@ -85,7 +85,7 @@ export async function getFarcasterMetadata(): Promise<MiniAppManifest> {
|
||||
} catch (error) {
|
||||
console.warn(
|
||||
'Failed to parse MINI_APP_METADATA from environment:',
|
||||
error
|
||||
error,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -101,7 +101,7 @@ export async function getFarcasterMetadata(): Promise<MiniAppManifest> {
|
||||
const secretEnvVars = getSecretEnvVars();
|
||||
if (!secretEnvVars) {
|
||||
console.warn(
|
||||
'No seed phrase or FID found in environment variables -- generating unsigned metadata'
|
||||
'No seed phrase or FID found in environment variables -- generating unsigned metadata',
|
||||
);
|
||||
}
|
||||
|
||||
@@ -117,7 +117,7 @@ export async function getFarcasterMetadata(): Promise<MiniAppManifest> {
|
||||
key: custodyAddress,
|
||||
};
|
||||
const encodedHeader = Buffer.from(JSON.stringify(header), 'utf-8').toString(
|
||||
'base64'
|
||||
'base64',
|
||||
);
|
||||
|
||||
const payload = {
|
||||
@@ -125,14 +125,14 @@ export async function getFarcasterMetadata(): Promise<MiniAppManifest> {
|
||||
};
|
||||
const encodedPayload = Buffer.from(
|
||||
JSON.stringify(payload),
|
||||
'utf-8'
|
||||
'utf-8',
|
||||
).toString('base64url');
|
||||
|
||||
const signature = await account.signMessage({
|
||||
message: `${encodedHeader}.${encodedPayload}`,
|
||||
});
|
||||
const encodedSignature = Buffer.from(signature, 'utf-8').toString(
|
||||
'base64url'
|
||||
'base64url',
|
||||
);
|
||||
|
||||
accountAssociation = {
|
||||
|
||||
Reference in New Issue
Block a user