import { validChains } from "@abstract-foundation/agw-client";
import {
type LoginMethodOrderOption,
PrivyProvider,
type PrivyProviderProps,
} from "@privy-io/react-auth";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import React from "react";
import type { Chain, Transport } from "viem";
import { createConfig, http, WagmiProvider } from "wagmi";
import { AGW_APP_ID } from "../constants.js";
import { InjectWagmiConnector } from "./injectWagmiConnector.js";
export const agwAppLoginMethod: LoginMethodOrderOption = `privy:${AGW_APP_ID}`;
/**
* Configuration options for the AbstractPrivyProvider.
* @interface AgwPrivyProviderProps
* @extends PrivyProviderProps
* @property {boolean} testnet - Whether to use abstract testnet, defaults to false.
* @property {Transport} transport - Optional transport to use, defaults to standard http.
* @property {QueryClient} queryClient - Optional query client to use, defaults to a standard query client.
*/
interface AgwPrivyProviderProps extends PrivyProviderProps {
chain: Chain;
transport?: Transport;
queryClient?: QueryClient;
}
/**
* Provider component that integrates Abstract Global Wallet with Privy authentication.
*
* This component wraps your application with the necessary providers to use Abstract Global Wallet
* with Privy authentication, including:
* - PrivyProvider: Handles user authentication and EOA creation
* - WagmiProvider: Provides web3 functionality
* - QueryClientProvider: Manages data fetching with TanStack Query
* - InjectWagmiConnector: Injects the Abstract wallet into Wagmi
*
* @param props - Props for the AbstractPrivyProvider component
* @param props.chain - The blockchain network to connect to (must be supported by Abstract)
* @param props.transport - Optional transport for network requests (defaults to http)
* @param props.queryClient - Optional TanStack Query client (defaults to a new QueryClient)
* @param props.appId - Your Privy app ID (required)
* @param props.config - Optional Privy configuration (defaults to using Abstract as primary login)
* @returns A provider component that wraps your application
*
* @example
* ```tsx
* import { AbstractPrivyProvider } from "@abstract-foundation/agw-react/privy";
* import { abstract } from "viem/chains";
*
* function App() {
* return (
*
*
*
* );
* }
* ```
*
* Once your app is wrapped with this provider, you can use all the Abstract and Wagmi hooks
* throughout your application to interact with blockchain and manage user authentication.
*
* @see {@link useAbstractPrivyLogin} - Hook to login users with Abstract Global Wallet via Privy
* @see {@link useAbstractClient} - Hook to get an Abstract client for blockchain interactions
*/
export const AbstractPrivyProvider = ({
chain,
transport,
queryClient = new QueryClient(),
...props
}: AgwPrivyProviderProps) => {
if (!validChains[chain.id]) {
throw new Error(`Chain ${chain.id} is not supported`);
}
const wagmiConfig = createConfig({
chains: [chain],
ssr: true,
connectors: [],
transports: {
[chain.id]:
transport ??
http(undefined, {
batch: true,
}),
},
multiInjectedProviderDiscovery: false,
});
// if no login methods and order are provided, set the default login method to the privy app login method
if (!props.config) {
props.config = {
loginMethodsAndOrder: {
primary: [agwAppLoginMethod],
},
};
} else if (!props.config.loginMethodsAndOrder) {
props.config.loginMethodsAndOrder = {
primary: [agwAppLoginMethod],
};
}
return (
{props.children}
);
};