UNPKG

@prepaid-gas/data

Version:

Data layer for Prepaid Gas with fluent query builders

1,322 lines (1,306 loc) 40.9 kB
import { PaymasterType, ChainId } from '@prepaid-gas/constants'; /** * TypeScript type definitions for the paymaster subgraph (Updated) * Based on the new single-pool-per-contract architecture * * These types exactly match the new GraphQL schema entities: * - PaymasterContract (each contract IS a pool) * - Activity (unified timeline of all events) * - UserOperation (detailed operation tracking) */ /** * ======================================== * ENUMS * ======================================== */ /** * Activity types for the unified timeline */ type ActivityType = 'DEPOSIT' | 'USER_OP_SPONSORED' | 'REVENUE_WITHDRAWN'; /** * ======================================== * CORE ENTITY TYPES (exact match to schema) * ======================================== */ /** * PaymasterContract entity * Each contract IS a pool (no separate Pool entity) */ interface PaymasterContract { /** Unique identifier: network-contractAddress */ id: string; /** Contract type: "OneTimeUse", "GasLimited", "CacheEnabledGasLimited" */ contractType: PaymasterType; /** Contract address */ address: string; /** Network identifier (e.g., "base-sepolia") */ network: string; /** Chain ID (e.g., 84532 for Base Sepolia) */ chainId: bigint; /** Pool configuration (since each contract IS a pool) */ joiningAmount: bigint; scope: bigint; verifier: string; /** Financial tracking */ totalDeposit: bigint; currentDeposit: bigint; revenue: bigint; /** Merkle tree state */ root: bigint; rootIndex: bigint; treeDepth: bigint; treeSize: bigint; /** Pool status */ isDead: boolean; /** Deployment info */ deployedBlock: bigint; deployedTransaction: string; deployedTimestamp: bigint; /** Activity tracking */ lastBlock: bigint; lastTimestamp: bigint; /** Relationships */ activities: Activity[]; } /** * Activity entity * Unified timeline of all significant events */ interface Activity { /** Unique identifier: network-contractAddress-txHash-logIndex */ id: string; /** Activity type */ type: ActivityType; /** Paymaster contract this activity belongs to */ paymaster: PaymasterContract; /** Network identifier */ network: string; /** Chain ID */ chainId: bigint; /** Common event data */ block: bigint; transaction: string; timestamp: bigint; /** Deposit-specific fields (when type = DEPOSIT) */ depositor?: string; commitment?: bigint; memberIndex?: bigint; newRoot?: bigint; /** UserOperation-specific fields (when type = USER_OP_SPONSORED) */ sender?: string; userOpHash?: string; actualGasCost?: bigint; /** RevenueWithdrawal-specific fields (when type = REVENUE_WITHDRAWN) */ withdrawAddress?: string; amount?: bigint; } /** * UserOperation entity * Detailed user operation tracking for specialized analytics */ interface UserOperation { /** Unique identifier: network-contractAddress-userOpHash */ id: string; /** User operation hash */ hash: string; /** Paymaster that sponsored this operation */ paymaster: PaymasterContract; /** Network identifier */ network: string; /** Chain ID */ chainId: bigint; /** Operation details */ sender: string; actualGasCost: bigint; nullifier: bigint; /** Execution info */ block: bigint; transaction: string; timestamp: bigint; } /** * ======================================== * SERIALIZED TYPES (for API responses) * ======================================== */ /** * Serialized PaymasterContract (BigInt -> string) */ interface SerializedPaymasterContract { id: string; contractType: PaymasterType; address: string; network: string; chainId: string; joiningAmount: string; scope: string; verifier: string; totalDeposit: string; currentDeposit: string; revenue: string; root: string; rootIndex: string; treeDepth: string; treeSize: string; isDead: boolean; deployedBlock: string; deployedTransaction: string; deployedTimestamp: string; lastBlock: string; lastTimestamp: string; activities: SerializedActivity[]; } /** * Serialized Activity (BigInt -> string) */ interface SerializedActivity { id: string; type: ActivityType; paymaster: SerializedPaymasterContract; network: string; chainId: string; block: string; transaction: string; timestamp: string; depositor?: string; commitment?: string; memberIndex?: string; newRoot?: string; sender?: string; userOpHash?: string; actualGasCost?: string; withdrawAddress?: string; amount?: string; } /** * Serialized UserOperation (BigInt -> string) */ interface SerializedUserOperation { id: string; hash: string; paymaster: SerializedPaymasterContract; network: string; chainId: string; sender: string; actualGasCost: string; nullifier: string; block: string; transaction: string; timestamp: string; } /** * ======================================== * UTILITY TYPES * ======================================== */ /** * Entity types for type guards */ type EntityType = 'PaymasterContract' | 'Activity' | 'UserOperation'; /** * Deposit Activity - has deposit-specific fields guaranteed to be present */ interface DepositActivity extends Omit<Activity, 'type'> { type: 'DEPOSIT'; depositor: string; commitment: bigint; memberIndex?: bigint; newRoot?: bigint; sender?: undefined; userOpHash?: undefined; actualGasCost?: undefined; withdrawAddress?: undefined; amount?: undefined; } /** * User Operation Activity - has user op-specific fields guaranteed to be present */ interface UserOpActivity extends Omit<Activity, 'type'> { type: 'USER_OP_SPONSORED'; sender: string; userOpHash: string; actualGasCost: bigint; depositor?: undefined; commitment?: undefined; memberIndex?: undefined; newRoot?: undefined; withdrawAddress?: undefined; amount?: undefined; } /** * Revenue Withdrawal Activity - has revenue-specific fields guaranteed to be present */ interface RevenueActivity extends Omit<Activity, 'type'> { type: 'REVENUE_WITHDRAWN'; withdrawAddress: string; amount: bigint; depositor?: undefined; commitment?: undefined; memberIndex?: undefined; newRoot?: undefined; sender?: undefined; userOpHash?: undefined; actualGasCost?: undefined; } /** * Serialized versions for API responses */ interface SerializedDepositActivity extends Omit<DepositActivity, 'commitment' | 'memberIndex' | 'newRoot' | 'block' | 'timestamp' | 'chainId' | 'paymaster'> { commitment: string; memberIndex?: string; newRoot?: string; block: string; timestamp: string; chainId: string; paymaster: SerializedPaymasterContract; } interface SerializedUserOpActivity extends Omit<UserOpActivity, 'actualGasCost' | 'block' | 'timestamp' | 'chainId' | 'paymaster'> { actualGasCost: string; block: string; timestamp: string; chainId: string; paymaster: SerializedPaymasterContract; } interface SerializedRevenueActivity extends Omit<RevenueActivity, 'amount' | 'block' | 'timestamp' | 'chainId' | 'paymaster'> { amount: string; block: string; timestamp: string; chainId: string; paymaster: SerializedPaymasterContract; } /** * Type mapping for activity types to their interfaces */ interface ActivityTypeMap { DEPOSIT: DepositActivity; USER_OP_SPONSORED: UserOpActivity; REVENUE_WITHDRAWN: RevenueActivity; } /** * Type mapping for serialized activity types */ interface SerializedActivityTypeMap { DEPOSIT: SerializedDepositActivity; USER_OP_SPONSORED: SerializedUserOpActivity; REVENUE_WITHDRAWN: SerializedRevenueActivity; } /** * Network metadata for client configuration */ interface NetworkMetadata { /** Network name */ network: string; /** Chain ID */ chainId: number; /** Chain name (e.g., "Base Sepolia") */ chainName: string; /** Network name for display */ networkName: string; /** Contract addresses */ contracts: { /** Paymaster contracts by type */ paymasters: { gasLimited?: string; oneTimeUse?: string; cacheEnabledGasLimited?: string; }; /** Verifier contract (if applicable) */ verifier?: string; }; } /** * Core query builder types and interfaces (Updated) * For the new single-pool-per-contract architecture * * Supports queries for: * - PaymasterContract (each contract IS a pool) * - Activity (unified timeline of all events) * - UserOperation (detailed operation tracking) */ /** * Base query configuration for GraphQL queries */ interface QueryConfig<TWhereInput, TOrderBy> { /** Number of items to fetch */ first?: number; /** Number of items to skip (for pagination) */ skip?: number; /** Field to order by */ orderBy?: TOrderBy; /** Order direction */ orderDirection?: 'asc' | 'desc'; /** Where conditions */ where?: Partial<TWhereInput>; /** Network name */ network?: string; /** For dynamic field selection */ selectedFields?: string[]; } /** * ======================================== * FIELD TYPE DEFINITIONS (Updated) * ======================================== */ /** * Available fields for PaymasterContract entity queries */ type PaymasterContractFields = keyof PaymasterContract | 'activities { id type timestamp sender userOpHash actualGasCost }' | 'activities { id type depositor commitment memberIndex newRoot }' | 'activities { id type withdrawAddress amount }'; /** * Available fields for Activity entity queries */ type ActivityFields = keyof Activity | 'paymaster { id address contractType network }' | 'paymaster { joiningAmount scope verifier }'; /** * Available fields for UserOperation entity queries */ type UserOperationFields = keyof UserOperation | 'paymaster { id address contractType network }'; /** * ======================================== * ORDER BY TYPES (Updated) * ======================================== */ /** * Available order by fields for PaymasterContract */ type PaymasterContractOrderBy = 'id' | 'contractType' | 'network' | 'totalDeposit' | 'currentDeposit' | 'revenue' | 'treeSize' | 'deployedBlock' | 'deployedTimestamp' | 'lastBlock' | 'lastTimestamp'; /** * Available order by fields for Activity */ type ActivityOrderBy = 'id' | 'type' | 'network' | 'block' | 'timestamp' | 'actualGasCost' | 'amount'; /** * Available order by fields for UserOperation */ type UserOperationOrderBy = 'id' | 'network' | 'sender' | 'actualGasCost' | 'nullifier' | 'block' | 'timestamp'; /** * Typed where conditions for PaymasterContract entity */ interface PaymasterContractWhereInput { id?: string; network?: string; contractType?: PaymasterType; address?: string; totalDeposit_gte?: string; totalDeposit_lte?: string; currentDeposit_gte?: string; currentDeposit_lte?: string; revenue_gte?: string; revenue_lte?: string; revenue_gt?: string; treeSize_gte?: string; treeSize_lte?: string; treeSize_gt?: string; joiningAmount_gte?: string; joiningAmount_lte?: string; scope?: string; verifier?: string; isDead?: boolean; deployedTimestamp_gte?: string; deployedTimestamp_lte?: string; lastTimestamp_gte?: string; lastTimestamp_lte?: string; } /** * Typed where conditions for Activity entity */ interface ActivityWhereInput { id?: string; type?: ActivityType; network?: string; paymaster?: string; paymaster_?: { address?: string; contractType?: PaymasterType; network?: string; }; block_gte?: string; block_lte?: string; timestamp_gte?: string; timestamp_lte?: string; depositor?: string; commitment?: string; memberIndex_gte?: string; memberIndex_lte?: string; sender?: string; userOpHash?: string; actualGasCost_gte?: string; actualGasCost_lte?: string; withdrawAddress?: string; amount_gte?: string; amount_lte?: string; } /** * Typed where conditions for UserOperation entity */ interface UserOperationWhereInput { id?: string; hash?: string; network?: string; paymaster?: string; paymaster_?: { address?: string; contractType?: PaymasterType; network?: string; }; sender?: string; actualGasCost_gte?: string; actualGasCost_lte?: string; nullifier?: string; block_gte?: string; block_lte?: string; timestamp_gte?: string; timestamp_lte?: string; } /** * Base query builder with common functionality * * This abstract class provides the foundation for all entity-specific query builders. * Each concrete builder must implement the three core methods with proper typing. * * @template TEntity - The raw entity type from GraphQL (Pool, PaymasterContract, etc.) * @template TSerializedEntity - The serialized entity type (SerializedPool, etc.) * @template TFields - Union type of available fields for the entity * @template TWhereInput - Type for where condition input for the entity * @template TOrderBy - Union type of valid orderBy fields */ declare abstract class BaseQueryBuilder<TEntity, TSerializedEntity, TFields extends string, TWhereInput, TOrderBy extends string> { protected client: SubgraphClient; protected entityName: string; protected config: QueryConfig<TWhereInput, TOrderBy>; private static readonly MAX_SAFE_LIMIT; private static readonly DEFAULT_LIMIT; constructor(client: SubgraphClient, entityName: string, defaultOrderBy: TOrderBy, defaultOrderDirection?: 'asc' | 'desc'); /** * Build the GraphQL query string with proper types and validation * Each builder knows its own schema and field types */ protected abstract buildDynamicQuery(): string; /** * Build variables object with proper type conversion * Each builder handles its own BigInt/string conversions */ protected abstract buildVariables(): Record<string, any>; /** * Build where clause string with typed fields and validation * Each builder validates its own where conditions */ protected abstract buildWhereClauseString(): string; /** * Get the serializer function for this entity type * Each builder provides its own serializer from transformers */ protected abstract getSerializer(): (entity: TEntity) => TSerializedEntity; /** * Select specific fields to be returned * @param fields - Array of field names to select * @returns The query builder instance for chaining */ select(fields: TFields[]): this; /** * Add where conditions to the query * @param where - Object representing where conditions * @returns The query builder instance for chaining */ where(where: Partial<TWhereInput>): this; private deepMergeWhereConditions; /** * Limit the number of results * @param limit - Maximum number of results (capped at 1000 for safety) * @returns The query builder instance for chaining */ limit(limit: number): this; /** * Skip a number of results for pagination * @param skip - Number of results to skip * @returns The query builder instance for chaining */ skip(skip: number): this; /** * Set the ordering for the results * @param orderBy - Field to order by * @param direction - Order direction ("asc" or "desc") * @returns The query builder instance for chaining */ orderBy(orderBy: TOrderBy, direction?: 'asc' | 'desc'): this; /** * Execute the query and return raw entities * @returns Promise resolving to an array of TEntity */ execute(): Promise<TEntity[]>; /** * Execute the query and return properly typed serialized entities * @returns Promise resolving to an array of TSerializedEntity (not any!) */ executeAndSerialize(): Promise<TSerializedEntity[]>; /** * Execute the query and return the first result * @returns Promise resolving to the first TEntity or null */ first(): Promise<TEntity | null>; /** * Execute the query and return the first result as serialized entity * @returns Promise resolving to the first TSerializedEntity or null */ firstSerialized(): Promise<TSerializedEntity | null>; /** * Execute the query and check if any results exist * @returns Promise resolving to true if any results exist */ exists(): Promise<boolean>; /** * Execute the query and return the count of results * Note: This fetches all results and counts them * @returns Promise resolving to the count of matching entities */ count(): Promise<number>; /** * Clone the current query builder instance * @returns A new instance of the query builder with the same configuration */ clone(): this; /** * Get current query configuration (for debugging) * @returns Current configuration object */ getConfig(): QueryConfig<TWhereInput, TOrderBy>; /** * Reset the query builder to default state * @returns The query builder instance for chaining */ reset(): this; } /** * Query builder for PaymasterContract entities (Updated) * For the new single-pool-per-contract architecture */ /** * Query builder for PaymasterContract entities * * Provides a fluent interface for building complex paymaster queries * Updated for the new single-pool-per-contract schema. */ declare class PaymasterContractQueryBuilder extends BaseQueryBuilder<PaymasterContract, SerializedPaymasterContract, PaymasterContractFields, PaymasterContractWhereInput, PaymasterContractOrderBy> { private subgraphClient; constructor(subgraphClient: SubgraphClient); protected buildDynamicQuery(): string; protected buildVariables(): Record<string, any>; protected buildWhereClauseString(): string; protected getSerializer(): (entity: PaymasterContract) => SerializedPaymasterContract; private getVariableDeclarations; private addVariableDeclarations; private addWhereVariables; private buildWhereConditions; /** * Override default fields for PaymasterContract entity. */ protected getDefaultFields(): string; /** * Get fields with activities included */ private getFieldsWithActivities; /** * ======================================== * FILTERING METHODS * ======================================== */ /** * Filter by network */ byNetwork(network: string): this; /** * Filter by contract type */ byContractType(type: PaymasterType): this; /** * Filter by contract address */ byAddress(address: string): this; /** * Filter by composite ID (network-address) */ byId(network: string, address: string): this; /** * Filter by deployment date (after) */ deployedAfter(timestamp: string | number): this; /** * Filter by deployment date (before) */ deployedBefore(timestamp: string | number): this; /** * Filter only active paymasters (positive revenue) */ onlyActive(): this; /** * Filter only alive paymasters (not dead) */ onlyAlive(): this; /** * Include activities in the query results * This replaces the need to manually select activities fields */ withActivities(): this; /** * ======================================== * ORDERING METHODS * ======================================== */ /** * Order by revenue (highest first) */ orderByRevenue(direction?: 'asc' | 'desc'): this; /** * Order by total deposit */ orderByTotalDeposit(direction?: 'asc' | 'desc'): this; /** * Order by current deposit */ orderByDeposit(direction?: 'asc' | 'desc'): this; /** * Order by number of members (tree size) */ orderByMembers(direction?: 'asc' | 'desc'): this; /** * Order by deployment date */ orderByDeployment(direction?: 'asc' | 'desc'): this; /** * Order by last activity */ orderByActivity(direction?: 'asc' | 'desc'): this; } /** * Query builder for Activity entities * For the unified timeline of all paymaster events * Supports type-safe filtering by activity type */ /** * Base Activity Query Builder * Generic type T allows for typed results based on activity type */ declare class ActivityQueryBuilder<T extends Activity = Activity, S extends SerializedActivity = SerializedActivity> extends BaseQueryBuilder<T, S, ActivityFields, ActivityWhereInput, ActivityOrderBy> { private subgraphClient; constructor(subgraphClient: SubgraphClient); protected buildDynamicQuery(): string; protected buildVariables(): Record<string, any>; protected buildWhereClauseString(): string; protected getSerializer(): (entity: T) => S; private getVariableDeclarations; private addVariableDeclarations; private addWhereVariables; private buildWhereConditions; /** * Override default fields for Activity entity. */ protected getDefaultFields(): string; /** * ======================================== * FILTERING METHODS * ======================================== */ /** * Filter by activity type (generic version) */ byType(type: ActivityType): this; /** * ======================================== * TYPED FILTERING METHODS * ======================================== */ /** * Filter by activity type with type narrowing * Returns a typed query builder for the specific activity type */ byTyped<K extends keyof ActivityTypeMap>(type: K): ActivityQueryBuilder<ActivityTypeMap[K], SerializedActivityTypeMap[K]>; /** * Filter by network */ byNetwork(network: string): this; /** * Filter by paymaster address */ byPaymasterAddress(address: string): this; /** * Filter by paymaster contract type */ byPaymasterType(contractType: PaymasterType): this; /** * Filter activities after timestamp */ afterTimestamp(timestamp: string | number): this; /** * Filter activities before timestamp */ beforeTimestamp(timestamp: string | number): this; /** * Filter activities after block */ afterBlock(block: string | number): this; /** * Filter activities before block */ beforeBlock(block: string | number): this; /** * ======================================== * DEPOSIT-SPECIFIC FILTERING * ======================================== */ /** * Filter deposit activities by depositor */ byDepositor(depositor: string): this; /** * Filter deposit activities by commitment */ byCommitment(commitment: string): this; /** * Filter deposit activities by minimum member index */ withMinMemberIndex(minIndex: string): this; /** * Filter deposit activities by maximum member index */ withMaxMemberIndex(maxIndex: string): this; /** * ======================================== * USER_OP-SPECIFIC FILTERING * ======================================== */ /** * Filter user operation activities by sender */ bySender(sender: string): this; /** * Filter user operation activities by user op hash */ byUserOpHash(userOpHash: string): this; /** * Filter user operation activities by minimum gas cost */ withMinGasCost(minGasCost: string): this; /** * Filter user operation activities by maximum gas cost */ withMaxGasCost(maxGasCost: string): this; /** * ======================================== * REVENUE-SPECIFIC FILTERING * ======================================== */ /** * Filter revenue withdrawal activities by withdraw address */ byWithdrawAddress(withdrawAddress: string): this; /** * Filter revenue withdrawal activities by minimum amount */ withMinAmount(minAmount: string): this; /** * Filter revenue withdrawal activities by maximum amount */ withMaxAmount(maxAmount: string): this; /** * ======================================== * TYPED CONVENIENCE FILTERS * ======================================== */ /** * Filter only deposit activities (returns typed DepositActivity[]) */ onlyDeposits(): ActivityQueryBuilder<DepositActivity, SerializedDepositActivity>; /** * Filter only revenue withdrawal activities (returns typed RevenueActivity[]) */ onlyRevenueWithdrawals(): ActivityQueryBuilder<RevenueActivity, SerializedRevenueActivity>; /** * Filter only user operation activities * Note: For detailed user operations, use userOperations() query builder instead */ onlyUserOps(): this; /** * Filter activities within a time range */ betweenTimestamps(startTimestamp: string | number, endTimestamp: string | number): this; /** * Filter activities within a block range */ betweenBlocks(startBlock: string | number, endBlock: string | number): this; /** * ======================================== * ORDERING METHODS * ======================================== */ /** * Order by timestamp (most recent first by default) */ orderByTimestamp(direction?: 'asc' | 'desc'): this; /** * Order by block number */ orderByBlock(direction?: 'asc' | 'desc'): this; /** * Order by activity type */ orderByType(direction?: 'asc' | 'desc'): this; /** * Order by gas cost (for USER_OP_SPONSORED activities) */ orderByGasCost(direction?: 'asc' | 'desc'): this; /** * Order by amount (for REVENUE_WITHDRAWN activities) */ orderByAmount(direction?: 'asc' | 'desc'): this; } /** * Query builder for UserOperation entities * For detailed user operation tracking and analytics */ /** * Query builder for UserOperation entities * * Provides a fluent interface for building complex user operation queries * with support for paymaster filtering, gas analysis, and nullifier tracking. */ declare class UserOperationQueryBuilder extends BaseQueryBuilder<UserOperation, SerializedUserOperation, UserOperationFields, UserOperationWhereInput, UserOperationOrderBy> { private subgraphClient; constructor(subgraphClient: SubgraphClient); protected buildDynamicQuery(): string; protected buildVariables(): Record<string, any>; protected buildWhereClauseString(): string; protected getSerializer(): (entity: UserOperation) => SerializedUserOperation; private getVariableDeclarations; private addVariableDeclarations; private addWhereVariables; private buildWhereConditions; /** * Override default fields for UserOperation entity. */ protected getDefaultFields(): string; /** * ======================================== * FILTERING METHODS * ======================================== */ /** * Filter by network */ byNetwork(network: string): this; /** * Filter by user operation hash */ byHash(hash: string): this; /** * Filter by composite ID (network-contractAddress-userOpHash) */ byId(id: string): this; /** * Filter by paymaster ID */ byPaymaster(paymasterId: string): this; /** * Filter by paymaster address */ byPaymasterAddress(address: string): this; /** * Filter by paymaster contract type */ byPaymasterType(contractType: PaymasterType): this; /** * Filter by sender address */ bySender(sender: string): this; /** * Filter by nullifier */ byNullifier(nullifier: string): this; /** * Filter by minimum gas cost */ withMinGasCost(minGasCost: string): this; /** * Filter by maximum gas cost */ withMaxGasCost(maxGasCost: string): this; /** * Filter user operations after timestamp */ afterTimestamp(timestamp: string | number): this; /** * Filter user operations before timestamp */ beforeTimestamp(timestamp: string | number): this; /** * Filter user operations after block */ afterBlock(block: string | number): this; /** * Filter user operations before block */ beforeBlock(block: string | number): this; /** * Filter user operations within a time range */ betweenTimestamps(startTimestamp: string | number, endTimestamp: string | number): this; /** * Filter user operations within a block range */ betweenBlocks(startBlock: string | number, endBlock: string | number): this; /** * ======================================== * ORDERING METHODS * ======================================== */ /** * Order by timestamp (most recent first by default) */ orderByTimestamp(direction?: 'asc' | 'desc'): this; /** * Order by block number */ orderByBlock(direction?: 'asc' | 'desc'): this; /** * Order by gas cost (highest first by default) */ orderByGasCost(direction?: 'asc' | 'desc'): this; /** * Order by sender address */ orderBySender(direction?: 'asc' | 'desc'): this; /** * Order by nullifier */ orderByNullifier(direction?: 'asc' | 'desc'): this; /** * ======================================== * ANALYTICS METHODS * ======================================== */ /** * Get gas statistics for user operations */ getGasStatistics(): Promise<{ totalOperations: number; totalGasCost: string; averageGasCost: string; minGasCost: string; maxGasCost: string; medianGasCost: string; }>; /** * Get user operation timeline */ getOperationTimeline(days?: number): Promise<Array<{ date: string; operations: number; totalGasCost: string; averageGasCost: string; uniqueSenders: number; }>>; /** * Get sender analysis */ getSenderAnalysis(): Promise<Array<{ sender: string; operationCount: number; totalGasCost: string; averageGasCost: string; firstOperation: string; lastOperation: string; }>>; } /** * ======================================== * CONVENIENCE FUNCTIONS * ======================================== */ /** * Get user operation by hash */ declare function getUserOperationByHash(client: SubgraphClient, hash: string, network: string): Promise<UserOperation | null>; /** * Get recent user operations */ declare function getRecentUserOperations(client: SubgraphClient, network: string, limit?: number): Promise<UserOperation[]>; /** * Get user operations by sender */ declare function getUserOperationsBySender(client: SubgraphClient, sender: string, network: string): Promise<UserOperation[]>; /** * Get user operations by paymaster */ declare function getUserOperationsByPaymaster(client: SubgraphClient, paymasterAddress: string, network: string): Promise<UserOperation[]>; /** * Get expensive user operations (high gas cost) */ declare function getExpensiveUserOperations(client: SubgraphClient, network: string, minGasCost: string, limit?: number): Promise<UserOperation[]>; /** * Main query builder for the paymaster subgraph (Updated) * Provides access to all entity-specific query builders * * This is the entry point for the fluent query API for the new * single-pool-per-contract architecture with 3 core entities: * - PaymasterContract (each contract IS a pool) * - Activity (unified timeline of all events) * - UserOperation (detailed operation tracking) */ /** * Main query builder that provides access to all entity-specific query builders * */ declare class QueryBuilder { private client; constructor(client: SubgraphClient); /** * ======================================== * ENTITY-SPECIFIC QUERY BUILDERS * ======================================== */ /** * Start building a query for paymaster contracts * Each contract IS a pool in the new architecture * * @returns PaymasterContractQueryBuilder for fluent query building * * @example * ```typescript * const paymasters = await client.query() * .paymasters() * .byNetwork("base-sepolia") * .byContractType("OneTimeUse") * .withMinRevenue("1000000000000000000") * .orderByRevenue() * .limit(10) * .execute(); * ``` */ paymasters(): PaymasterContractQueryBuilder; /** * Start building a query for activities * Unified timeline of all events (deposits, user ops, revenue withdrawals) * * @returns ActivityQueryBuilder for fluent query building * * @example * ```typescript * // Mixed timeline view - all activity types together * const activities = await client.query() * .activities() * .byNetwork("base-sepolia") * .byPaymaster("0x456...") * .afterTimestamp("1640995200") * .orderByTimestamp() * .limit(50) * .execute(); * * // For detailed user operation data with nullifier, use userOperations() instead * ``` */ activities(): ActivityQueryBuilder; /** * Start building a query for user operations * Detailed tracking for specialized analytics including nullifier data * * @returns UserOperationQueryBuilder for fluent query building * * @example * ```typescript * const userOps = await client.query() * .userOperations() * .byNetwork("base-sepolia") * .byPaymaster("0x456...") * .bySender("0x789...") * .withMinGasCost("1000000000000000") * .orderByTimestamp() * .limit(25) * .execute(); * ``` */ userOperations(): UserOperationQueryBuilder; /** * ======================================== * TYPED ACTIVITY QUERY BUILDERS * ======================================== */ /** * Start building a query for deposit activities only * Returns typed DepositActivity[] results * * @returns ActivityQueryBuilder<DepositActivity> for fluent query building * * @example * ```typescript * const deposits = await client.query() * .depositActivities() * .byNetwork("base-sepolia") * .byDepositor("0x123...") * .orderByTimestamp() * .limit(20) * .execute(); * ``` */ depositActivities(): ActivityQueryBuilder<DepositActivity, SerializedDepositActivity>; /** * Start building a query for revenue withdrawal activities only * Returns typed RevenueActivity[] results * * @returns ActivityQueryBuilder<RevenueActivity> for fluent query building * * @example * ```typescript * const revenues = await client.query() * .revenueActivities() * .byNetwork("base-sepolia") * .byWithdrawAddress("0x789...") * .withMinAmount("5000000000000000000") * .orderByAmount() * .limit(10) * .execute(); * ``` */ revenueActivities(): ActivityQueryBuilder<RevenueActivity, SerializedRevenueActivity>; } /** * Configuration for the subgraph client * Updated to support multiple paymaster contracts */ type SubClientOptions = { subgraphUrl?: string; timeout?: number; }; /** * Clean, focused subgraph client for data access * Handles GraphQL communication and basic data transformation * Updated for new PaymasterContract-based subgraph structure */ declare class SubgraphClient { private client; private chainId; private options; private requestMap; private readonly maxPendingRequests; constructor(chainId: ChainId, options?: SubClientOptions); /** * Generate a unique key for a query/variables combination * * @param query - GraphQL query string * @param variables - Query variables * @returns Unique key for the request */ private generateRequestKey; /** * Clean up completed request from the map * * @param requestKey - Key of the request to clean up */ private cleanupRequest; /** * Clean up old requests if map gets too large */ private cleanupOldRequests; /** * Create SubgraphClient for a specific network using presets * * @param chainId - The chain ID to create client for * @param options - Optional configuration overrides * @returns Configured SubgraphClient instance * * @example * ```typescript * // Create for Base Sepolia using preset * const client = SubgraphClient.createForNetwork(84532); * * // Create with custom subgraph URL override * const client = SubgraphClient.createForNetwork(84532, { * subgraphUrl: "https://custom-subgraph.com", * timeout: 60000 * }); * ``` */ static createForNetwork(chainId: ChainId, options?: { /** Custom subgraph URL (optional, uses preset default if not provided) */ subgraphUrl?: string; /** Request timeout in milliseconds */ timeout?: number; }): SubgraphClient; /** * ✨ Create a fluent query builder instance * * This is the main entry point for the new query builder API. * Provides a fluent interface for building complex queries with type safety. * * @returns QueryBuilder for fluent query building * * @example * ```typescript * // Simple paymaster query * const paymasters = await client * .query() * .paymasters() * .byType("GasLimited") * .withMinRevenue("1000000000000000000") * .orderByRevenue() * .limit(10) * .execute(); * * // Complex pool query with members * const pools = await client * .query() * .pools() * .byPaymaster("0x456...") * .withMinMembers(10) * .withMembers(50) * .orderByPopularity() * .limit(20) * .execute(); * * // Analytics query * const analytics = await client * .query() * .dailyGlobalStats() * .forDateRange("2024-01-01", "2024-01-31") * .withMinNewPools(2) * .orderByNewest() * .execute(); * ``` */ query(): QueryBuilder; /** * Execute a raw GraphQL query with request deduplication * * This method provides a generic interface for executing any GraphQL query, * with built-in deduplication to prevent duplicate requests for identical queries. * * @template T - The expected response type * @param query - GraphQL query string * @param variables - Query variables object * @returns Promise resolving to the query response data * * @example * ```typescript * const response = await client.executeQuery<{ pools: Pool[] }>( * 'query GetPools($first: Int!) { pools(first: $first) { id poolId } }', * { first: 10 } * ); * console.log(response.pools); * ``` */ executeQuery<T = any>(query: string, variables?: Record<string, any>): Promise<T>; /** * Execute multiple queries in parallel with deduplication * * @param queries - Array of query objects with query string and variables * @returns Promise resolving to array of query responses * * @example * ```typescript * const results = await client.executeQueries([ * { query: 'query GetPools { pools { id } }', variables: {} }, * { query: 'query GetPaymasters { paymasterContracts { id } }', variables: {} } * ]); * ``` */ executeQueries<T = any>(queries: Array<{ query: string; variables?: Record<string, any>; }>): Promise<T[]>; } export { type Activity as A, BaseQueryBuilder as B, type EntityType as E, type NetworkMetadata as N, type PaymasterContract as P, QueryBuilder as Q, type SerializedPaymasterContract as S, UserOperationQueryBuilder as U, type ActivityType as a, type SerializedActivity as b, type SerializedUserOperation as c, SubgraphClient as d, PaymasterContractQueryBuilder as e, getRecentUserOperations as f, getUserOperationByHash as g, getUserOperationsBySender as h, getUserOperationsByPaymaster as i, getExpensiveUserOperations as j };