@pafi-dev/issuer 0.5.32 → 0.5.33

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.cts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { Address, Hex, PublicClient, WalletClient } from 'viem';
2
- import { PointTokenDomainConfig, PartialUserOperation, BurnRequest, PoolKey } from '@pafi-dev/core';
2
+ import { PointTokenDomainConfig, PartialUserOperation, BurnRequest, PoolKey, UserOpTypedData } from '@pafi-dev/core';
3
3
  export { PAFI_SUBGRAPH_URL } from '@pafi-dev/core';
4
4
 
5
5
  /**
@@ -32,6 +32,28 @@ interface LockedMintRequest {
32
32
  expiresAt: number;
33
33
  /** On-chain transaction hash, set once the mint is confirmed */
34
34
  txHash?: Hex;
35
+ /**
36
+ * ERC-4337 userOpHash returned by the bundler at submit time. Bound
37
+ * to the lock by `bindMintUserOpHash` so status endpoints can poll
38
+ * the bundler receipt directly — bypasses `PointIndexer`'s
39
+ * amount-based matching, which races when several PENDING locks
40
+ * share the same amount.
41
+ */
42
+ userOpHash?: Hex;
43
+ }
44
+ /** A pending off-chain credit (burn → credit reverse flow). */
45
+ interface PendingCredit {
46
+ lockId: string;
47
+ userAddress: Address;
48
+ amount: bigint;
49
+ tokenAddress?: Address;
50
+ status: "PENDING" | "RESOLVED" | "EXPIRED";
51
+ createdAt: number;
52
+ expiresAt: number;
53
+ txHash?: Hex;
54
+ resolvedAt?: number;
55
+ /** Bundler-returned userOpHash. See `LockedMintRequest.userOpHash`. */
56
+ userOpHash?: Hex;
35
57
  }
36
58
  /**
37
59
  * Issuer point ledger interface — the source of truth for off-chain user
@@ -92,6 +114,29 @@ interface IPointLedger {
92
114
  * Throws if the lockId is unknown or already resolved.
93
115
  */
94
116
  resolveCreditByBurnTx?(lockId: string, txHash: Hex): Promise<void>;
117
+ /**
118
+ * Persist the bundler-returned userOpHash for a mint lock at
119
+ * submit time. Called once per `/claim/submit` after the bundler
120
+ * accepts the UserOp.
121
+ */
122
+ bindMintUserOpHash?(lockId: string, userOpHash: Hex): Promise<void>;
123
+ /**
124
+ * Persist the bundler-returned userOpHash for a pending credit at
125
+ * `/redeem/submit` time.
126
+ */
127
+ bindCreditUserOpHash?(lockId: string, userOpHash: Hex): Promise<void>;
128
+ /**
129
+ * Look up a mint lock by id. Returns `null` if the lock doesn't
130
+ * exist or doesn't belong to the supplied user (when provided).
131
+ * Used by `handleClaimStatus` for status polling. OPTIONAL — when
132
+ * absent, callers must implement status endpoints themselves.
133
+ */
134
+ getMintLock?(lockId: string, userAddress?: Address): Promise<LockedMintRequest | null>;
135
+ /**
136
+ * Look up a pending credit by id. Symmetric counterpart of
137
+ * `getMintLock` for the burn/redeem flow.
138
+ */
139
+ getPendingCredit?(lockId: string, userAddress?: Address): Promise<PendingCredit | null>;
95
140
  }
96
141
 
97
142
  /**
@@ -1294,6 +1339,194 @@ declare class TopUpRedemptionHandler {
1294
1339
  handle(request: TopUpRedemptionRequest): Promise<TopUpRedemptionResponse>;
1295
1340
  }
1296
1341
 
1342
+ interface RetryConfig {
1343
+ maxAttempts?: number;
1344
+ initialDelayMs?: number;
1345
+ maxDelayMs?: number;
1346
+ maxRetryAfterMs?: number;
1347
+ }
1348
+ interface PafiBackendConfig {
1349
+ url: string;
1350
+ issuerId: string;
1351
+ apiKey: string;
1352
+ fetchImpl?: typeof fetch;
1353
+ timeoutMs?: number;
1354
+ retry?: RetryConfig;
1355
+ }
1356
+ type PafiBackendErrorCode = "MISSING_ISSUER_ID" | "MISSING_API_KEY" | "ISSUER_UNAUTHORIZED" | "USER_UNAUTHORIZED" | "INTENT_REJECTED" | "MINT_CAP_EXCEEDED" | "ISSUER_INACTIVE" | "BROKER_NOT_WHITELISTED" | "RATE_LIMIT_EXCEEDED" | "RATE_LIMIT_EXCEEDED_DAILY" | "RATE_LIMIT_EXCEEDED_PER_USER" | "ISSUER_BUDGET_EXCEEDED" | "RATE_LIMITER_UNAVAILABLE" | "PAYMASTER_UNAVAILABLE" | "TARGET_NOT_ALLOWLISTED" | "BAD_REQUEST" | "INTERNAL_ERROR" | "TIMEOUT" | "NETWORK_ERROR" | (string & {});
1357
+ declare class PafiBackendError extends Error {
1358
+ code: PafiBackendErrorCode;
1359
+ httpStatus: number;
1360
+ details?: unknown | undefined;
1361
+ readonly retryAfter?: number;
1362
+ private readonly serverSafeToRetry?;
1363
+ constructor(code: PafiBackendErrorCode, message: string, httpStatus: number, details?: unknown | undefined, opts?: {
1364
+ retryAfter?: number;
1365
+ safeToRetry?: boolean;
1366
+ });
1367
+ get safeToRetry(): boolean;
1368
+ }
1369
+
1370
+ interface RelayUserOpRequest {
1371
+ userOp: Record<string, string | null>;
1372
+ entryPoint: string;
1373
+ eip7702Auth?: {
1374
+ chainId: string;
1375
+ address: string;
1376
+ nonce: string;
1377
+ r: string;
1378
+ s: string;
1379
+ yParity: string;
1380
+ };
1381
+ }
1382
+ interface RelayUserOpResponse {
1383
+ userOpHash: Hex;
1384
+ }
1385
+ interface SponsorshipUserOp {
1386
+ sender: Address;
1387
+ nonce: bigint;
1388
+ callData: Hex;
1389
+ callGasLimit: bigint;
1390
+ verificationGasLimit: bigint;
1391
+ preVerificationGas: bigint;
1392
+ maxFeePerGas: bigint;
1393
+ maxPriorityFeePerGas: bigint;
1394
+ }
1395
+ interface SponsorshipTarget {
1396
+ contract: Address;
1397
+ function: string;
1398
+ pointToken: Address;
1399
+ }
1400
+ interface SponsorshipRequest {
1401
+ chainId: number;
1402
+ scenario: string;
1403
+ userOp: SponsorshipUserOp;
1404
+ target: SponsorshipTarget;
1405
+ }
1406
+ interface SponsorshipResponse {
1407
+ paymaster: Address;
1408
+ paymasterData: Hex;
1409
+ paymasterVerificationGasLimit: bigint;
1410
+ paymasterPostOpGasLimit: bigint;
1411
+ /**
1412
+ * Pimlico's `pm_sponsorUserOperation` re-estimates these gas fields
1413
+ * and signs its paymaster signature over the new values. Callers
1414
+ * MUST overwrite the matching userOp fields with these BEFORE
1415
+ * computing the EIP-712 userOpHash and submitting to the bundler.
1416
+ * Otherwise both `AA34` (paymaster sig) and `AA24` (sender sig) will
1417
+ * fire — the EntryPoint hashes the actual on-chain field values, and
1418
+ * a mismatch invalidates every sig over the hash.
1419
+ */
1420
+ callGasLimit?: bigint;
1421
+ verificationGasLimit?: bigint;
1422
+ preVerificationGas?: bigint;
1423
+ /**
1424
+ * Bundler-required gas price (Pimlico's `pimlico_getUserOperationGasPrice`
1425
+ * fast tier). Pimlico's paymaster signs over these — caller MUST apply
1426
+ * to the userOp before computing the EIP-712 userOpHash. Base RPC's
1427
+ * `eth_feeHistory` underestimates the bundler floor by 10-15 %, so
1428
+ * relying on it produces "maxFeePerGas must be at least ..." rejections.
1429
+ */
1430
+ maxFeePerGas?: bigint;
1431
+ maxPriorityFeePerGas?: bigint;
1432
+ expiresAt: number;
1433
+ }
1434
+ declare class PafiBackendClient {
1435
+ private readonly config;
1436
+ constructor(config: PafiBackendConfig);
1437
+ requestSponsorship(request: SponsorshipRequest): Promise<SponsorshipResponse>;
1438
+ /**
1439
+ * Fetch ERC-4337 UserOp receipt via PAFI's authenticated bundler proxy.
1440
+ * Returns `null` when the bundler hasn't seen the userOp yet — caller
1441
+ * should keep polling. Used by status endpoints to short-circuit the
1442
+ * on-chain indexer when several PENDING locks share the same amount.
1443
+ */
1444
+ getUserOpReceipt(userOpHash: Hex): Promise<{
1445
+ success: boolean;
1446
+ txHash: Hex;
1447
+ blockNumber: string;
1448
+ } | null>;
1449
+ relayUserOperation(request: RelayUserOpRequest): Promise<RelayUserOpResponse>;
1450
+ private _doRequest;
1451
+ }
1452
+
1453
+ /**
1454
+ * Status snapshot returned to mobile clients polling a mint lock.
1455
+ * Matches the legacy gg56 shape so existing FE code keeps working.
1456
+ */
1457
+ interface MintStatusResponse {
1458
+ lockId: string;
1459
+ status: "PENDING" | "MINTED" | "EXPIRED" | "FAILED";
1460
+ txHash: Hex | null;
1461
+ amount: string;
1462
+ createdAt: string;
1463
+ expiresAt: string;
1464
+ }
1465
+ interface BurnStatusResponse {
1466
+ lockId: string;
1467
+ status: "PENDING" | "RESOLVED" | "EXPIRED";
1468
+ txHash: Hex | null;
1469
+ amount: string;
1470
+ createdAt: string;
1471
+ expiresAt: string;
1472
+ resolvedAt?: string | null;
1473
+ }
1474
+ interface MintStatusParams {
1475
+ lockId: string;
1476
+ /** User EOA from auth — handler returns 404 if the lock isn't theirs. */
1477
+ userAddress: Address;
1478
+ ledger: IPointLedger;
1479
+ /**
1480
+ * PAFI backend client for the bundler-receipt fallback. Optional —
1481
+ * when omitted, status only reflects what the on-chain `PointIndexer`
1482
+ * has finalized into the ledger. With it, the handler queries the
1483
+ * bundler receipt when:
1484
+ * - lock.status === "PENDING"
1485
+ * - lock.userOpHash is bound (set by `/claim/submit`)
1486
+ *
1487
+ * If the bundler reports the UserOp confirmed, the handler updates
1488
+ * the ledger lock + returns `MINTED` immediately, bypassing
1489
+ * `PointIndexer`'s amount-based race (multiple PENDING locks with
1490
+ * the same amount can be matched to the wrong tx_hash).
1491
+ */
1492
+ pafiBackendClient?: PafiBackendClient;
1493
+ /** Optional logger for "ledger update failed" warnings. */
1494
+ onWarning?: (msg: string) => void;
1495
+ }
1496
+ interface BurnStatusParams {
1497
+ lockId: string;
1498
+ userAddress: Address;
1499
+ ledger: IPointLedger;
1500
+ pafiBackendClient?: PafiBackendClient;
1501
+ onWarning?: (msg: string) => void;
1502
+ }
1503
+ declare class LockNotFoundError extends Error {
1504
+ readonly code = "LOCK_NOT_FOUND";
1505
+ constructor();
1506
+ }
1507
+
1508
+ /**
1509
+ * Handle GET /claim/status/:lockId.
1510
+ *
1511
+ * Returns the lock's current state from the ledger. When the ledger
1512
+ * supports `userOpHash` binding AND the lock is still PENDING, falls
1513
+ * back to the bundler receipt — the canonical truth that bypasses
1514
+ * `PointIndexer`'s amount-based matching race.
1515
+ *
1516
+ * Throws `LockNotFoundError` when the lock doesn't exist or doesn't
1517
+ * belong to `userAddress`. Caller maps to HTTP 404.
1518
+ */
1519
+ declare function handleClaimStatus(params: MintStatusParams): Promise<MintStatusResponse>;
1520
+ /**
1521
+ * Handle GET /redeem/status/:lockId. Symmetric to `handleClaimStatus`
1522
+ * for the burn → off-chain credit flow.
1523
+ *
1524
+ * Bundler-receipt fallback resolves the credit via
1525
+ * `ledger.resolveCreditByBurnTx` when the bundler reports the burn
1526
+ * UserOp succeeded.
1527
+ */
1528
+ declare function handleRedeemStatus(params: BurnStatusParams): Promise<BurnStatusResponse>;
1529
+
1297
1530
  /**
1298
1531
  * Config for `createSubgraphPoolsProvider`.
1299
1532
  */
@@ -1511,117 +1744,6 @@ declare class BalanceAggregator {
1511
1744
  getCombinedBalanceMulti(user: Address, pointTokens: Address[]): Promise<Map<Address, CombinedBalance>>;
1512
1745
  }
1513
1746
 
1514
- interface RetryConfig {
1515
- maxAttempts?: number;
1516
- initialDelayMs?: number;
1517
- maxDelayMs?: number;
1518
- maxRetryAfterMs?: number;
1519
- }
1520
- interface PafiBackendConfig {
1521
- url: string;
1522
- issuerId: string;
1523
- apiKey: string;
1524
- fetchImpl?: typeof fetch;
1525
- timeoutMs?: number;
1526
- retry?: RetryConfig;
1527
- }
1528
- type PafiBackendErrorCode = "MISSING_ISSUER_ID" | "MISSING_API_KEY" | "ISSUER_UNAUTHORIZED" | "USER_UNAUTHORIZED" | "INTENT_REJECTED" | "MINT_CAP_EXCEEDED" | "ISSUER_INACTIVE" | "BROKER_NOT_WHITELISTED" | "RATE_LIMIT_EXCEEDED" | "RATE_LIMIT_EXCEEDED_DAILY" | "RATE_LIMIT_EXCEEDED_PER_USER" | "ISSUER_BUDGET_EXCEEDED" | "RATE_LIMITER_UNAVAILABLE" | "PAYMASTER_UNAVAILABLE" | "TARGET_NOT_ALLOWLISTED" | "BAD_REQUEST" | "INTERNAL_ERROR" | "TIMEOUT" | "NETWORK_ERROR" | (string & {});
1529
- declare class PafiBackendError extends Error {
1530
- code: PafiBackendErrorCode;
1531
- httpStatus: number;
1532
- details?: unknown | undefined;
1533
- readonly retryAfter?: number;
1534
- private readonly serverSafeToRetry?;
1535
- constructor(code: PafiBackendErrorCode, message: string, httpStatus: number, details?: unknown | undefined, opts?: {
1536
- retryAfter?: number;
1537
- safeToRetry?: boolean;
1538
- });
1539
- get safeToRetry(): boolean;
1540
- }
1541
-
1542
- interface RelayUserOpRequest {
1543
- userOp: Record<string, string | null>;
1544
- entryPoint: string;
1545
- eip7702Auth?: {
1546
- chainId: string;
1547
- address: string;
1548
- nonce: string;
1549
- r: string;
1550
- s: string;
1551
- yParity: string;
1552
- };
1553
- }
1554
- interface RelayUserOpResponse {
1555
- userOpHash: Hex;
1556
- }
1557
- interface SponsorshipUserOp {
1558
- sender: Address;
1559
- nonce: bigint;
1560
- callData: Hex;
1561
- callGasLimit: bigint;
1562
- verificationGasLimit: bigint;
1563
- preVerificationGas: bigint;
1564
- maxFeePerGas: bigint;
1565
- maxPriorityFeePerGas: bigint;
1566
- }
1567
- interface SponsorshipTarget {
1568
- contract: Address;
1569
- function: string;
1570
- pointToken: Address;
1571
- }
1572
- interface SponsorshipRequest {
1573
- chainId: number;
1574
- scenario: string;
1575
- userOp: SponsorshipUserOp;
1576
- target: SponsorshipTarget;
1577
- }
1578
- interface SponsorshipResponse {
1579
- paymaster: Address;
1580
- paymasterData: Hex;
1581
- paymasterVerificationGasLimit: bigint;
1582
- paymasterPostOpGasLimit: bigint;
1583
- /**
1584
- * Pimlico's `pm_sponsorUserOperation` re-estimates these gas fields
1585
- * and signs its paymaster signature over the new values. Callers
1586
- * MUST overwrite the matching userOp fields with these BEFORE
1587
- * computing the EIP-712 userOpHash and submitting to the bundler.
1588
- * Otherwise both `AA34` (paymaster sig) and `AA24` (sender sig) will
1589
- * fire — the EntryPoint hashes the actual on-chain field values, and
1590
- * a mismatch invalidates every sig over the hash.
1591
- */
1592
- callGasLimit?: bigint;
1593
- verificationGasLimit?: bigint;
1594
- preVerificationGas?: bigint;
1595
- /**
1596
- * Bundler-required gas price (Pimlico's `pimlico_getUserOperationGasPrice`
1597
- * fast tier). Pimlico's paymaster signs over these — caller MUST apply
1598
- * to the userOp before computing the EIP-712 userOpHash. Base RPC's
1599
- * `eth_feeHistory` underestimates the bundler floor by 10-15 %, so
1600
- * relying on it produces "maxFeePerGas must be at least ..." rejections.
1601
- */
1602
- maxFeePerGas?: bigint;
1603
- maxPriorityFeePerGas?: bigint;
1604
- expiresAt: number;
1605
- }
1606
- declare class PafiBackendClient {
1607
- private readonly config;
1608
- constructor(config: PafiBackendConfig);
1609
- requestSponsorship(request: SponsorshipRequest): Promise<SponsorshipResponse>;
1610
- /**
1611
- * Fetch ERC-4337 UserOp receipt via PAFI's authenticated bundler proxy.
1612
- * Returns `null` when the bundler hasn't seen the userOp yet — caller
1613
- * should keep polling. Used by status endpoints to short-circuit the
1614
- * on-chain indexer when several PENDING locks share the same amount.
1615
- */
1616
- getUserOpReceipt(userOpHash: Hex): Promise<{
1617
- success: boolean;
1618
- txHash: Hex;
1619
- blockNumber: string;
1620
- } | null>;
1621
- relayUserOperation(request: RelayUserOpRequest): Promise<RelayUserOpResponse>;
1622
- private _doRequest;
1623
- }
1624
-
1625
1747
  /**
1626
1748
  * Top-level configuration for `createIssuerService`.
1627
1749
  *
@@ -1814,6 +1936,154 @@ interface IPendingUserOpStore {
1814
1936
  */
1815
1937
  declare function serializeEntryToJsonRpc(entry: PendingUserOpEntry, signature: Hex, variant?: "sponsored" | "fallback"): Record<string, string | null>;
1816
1938
 
1939
+ /**
1940
+ * Re-shape `UserOpTypedData` so all `bigint` fields become hex strings —
1941
+ * required for JSON transport over HTTP. Mirrors the inverse of what
1942
+ * `walletClient.signTypedData` accepts on the client (it auto-coerces hex
1943
+ * strings back to bigints for `uint256` fields).
1944
+ */
1945
+ type SerializedUserOpTypedData = {
1946
+ domain: UserOpTypedData["domain"];
1947
+ types: UserOpTypedData["types"];
1948
+ primaryType: UserOpTypedData["primaryType"];
1949
+ message: {
1950
+ sender: Address;
1951
+ nonce: Hex;
1952
+ initCode: Hex;
1953
+ callData: Hex;
1954
+ accountGasLimits: Hex;
1955
+ preVerificationGas: Hex;
1956
+ gasFees: Hex;
1957
+ paymasterAndData: Hex;
1958
+ };
1959
+ };
1960
+ /**
1961
+ * Convert a `UserOpTypedData` payload into the JSON-safe wire form
1962
+ * (bigint → hex string). The mobile client passes this directly to
1963
+ * `eth_signTypedData_v4` / viem's `signTypedData`.
1964
+ */
1965
+ declare function serializeUserOpTypedData(td: UserOpTypedData): SerializedUserOpTypedData;
1966
+ /**
1967
+ * Merge Pimlico's paymaster-sponsorship response into a UserOp
1968
+ * skeleton, applying only fields that are actually defined.
1969
+ *
1970
+ * `pm_sponsorUserOperation` returns:
1971
+ * - `paymaster` / `paymasterData` — required for the sponsored sig
1972
+ * - `paymasterVerificationGasLimit` / `paymasterPostOpGasLimit`
1973
+ * - **re-estimated** `callGasLimit` / `verificationGasLimit` /
1974
+ * `preVerificationGas` — the paymaster signature is computed over
1975
+ * these new values
1976
+ * - **bundler-required** `maxFeePerGas` / `maxPriorityFeePerGas` —
1977
+ * Base RPC's `eth_feeHistory` underestimates, bundler rejects
1978
+ *
1979
+ * Callers MUST re-merge ALL of these into the userOp BEFORE computing
1980
+ * the EIP-712 userOpHash — otherwise both the paymaster signature
1981
+ * (AA34) and the user signature (AA24, recovered against a different
1982
+ * hash) fail at validation.
1983
+ *
1984
+ * Skips fields that are undefined so legacy paymaster responses
1985
+ * (without re-estimated gas) don't accidentally zero out the original
1986
+ * estimates.
1987
+ */
1988
+ declare function mergePaymasterFields<T extends object>(userOp: T, paymasterFields: {
1989
+ paymaster: Address;
1990
+ paymasterData: Hex;
1991
+ paymasterVerificationGasLimit: bigint;
1992
+ paymasterPostOpGasLimit: bigint;
1993
+ callGasLimit?: bigint;
1994
+ verificationGasLimit?: bigint;
1995
+ preVerificationGas?: bigint;
1996
+ maxFeePerGas?: bigint;
1997
+ maxPriorityFeePerGas?: bigint;
1998
+ } | undefined): T;
1999
+ interface PreparedUserOp {
2000
+ /** The bundler-ready UserOp (with paymaster + Pimlico-quoted gas). */
2001
+ userOp: PartialUserOperation & {
2002
+ maxFeePerGas: bigint;
2003
+ maxPriorityFeePerGas: bigint;
2004
+ paymaster?: Address;
2005
+ paymasterData?: Hex;
2006
+ paymasterVerificationGasLimit?: bigint;
2007
+ paymasterPostOpGasLimit?: bigint;
2008
+ };
2009
+ /** Hex-encoded EIP-712 digest. Equals `EntryPoint.getUserOpHash`. */
2010
+ userOpHash: Hex;
2011
+ /** Typed-data payload — pass directly to `eth_signTypedData_v4`. */
2012
+ typedData: SerializedUserOpTypedData;
2013
+ }
2014
+ interface PrepareMobileUserOpParams {
2015
+ /** Lock id (issuer-generated) keying both store entry + ledger row. */
2016
+ lockId: string;
2017
+ /**
2018
+ * Sponsored variant — built with the PT operator-fee transfer
2019
+ * included. SDK or caller should set `partialUserOp.maxFeePerGas` /
2020
+ * `maxPriorityFeePerGas` from `provider.estimateFeesPerGas()` before
2021
+ * calling — they get overridden by Pimlico's quote anyway, but
2022
+ * they must be valid bigints for the merge.
2023
+ */
2024
+ partialUserOp: PartialUserOperation & {
2025
+ maxFeePerGas: bigint;
2026
+ maxPriorityFeePerGas: bigint;
2027
+ };
2028
+ /**
2029
+ * Optional fee-stripped fallback variant — built with `gasFeePt: 0n`
2030
+ * (no PT operator-fee transfer). Submitted when paymaster refuses
2031
+ * sponsorship and the user pays ETH gas directly.
2032
+ */
2033
+ partialUserOpFallback?: PartialUserOperation & {
2034
+ maxFeePerGas?: bigint;
2035
+ maxPriorityFeePerGas?: bigint;
2036
+ };
2037
+ /** Paymaster sponsorship response, or `undefined` if PAFI declined. */
2038
+ paymasterFields?: {
2039
+ paymaster: Address;
2040
+ paymasterData: Hex;
2041
+ paymasterVerificationGasLimit: bigint;
2042
+ paymasterPostOpGasLimit: bigint;
2043
+ callGasLimit?: bigint;
2044
+ verificationGasLimit?: bigint;
2045
+ preVerificationGas?: bigint;
2046
+ maxFeePerGas?: bigint;
2047
+ maxPriorityFeePerGas?: bigint;
2048
+ };
2049
+ chainId: number;
2050
+ /** Pending-userop store implementation (Redis/Postgres/Memory). */
2051
+ store: IPendingUserOpStore;
2052
+ /** TTL the store entry should outlive — typically the MintRequest deadline. */
2053
+ ttlSeconds: number;
2054
+ }
2055
+ interface PrepareMobileUserOpResult {
2056
+ sponsored: PreparedUserOp;
2057
+ /**
2058
+ * Set when `partialUserOpFallback` was supplied AND the PT fee was
2059
+ * non-zero (i.e. sponsored ≠ fallback). Mobile client picks which
2060
+ * variant to sign + submit; SDK's `serializeEntryToJsonRpc` reads
2061
+ * the `variant` flag to dispatch.
2062
+ */
2063
+ fallback?: PreparedUserOp;
2064
+ /** What got persisted into the pending-userop store. */
2065
+ entry: PendingUserOpEntry;
2066
+ }
2067
+ /**
2068
+ * Build the sponsored UserOp + (optional) fee-stripped fallback for the
2069
+ * mobile prepare/submit flow.
2070
+ *
2071
+ * What this does, end-to-end:
2072
+ * 1. Merge Pimlico's paymaster sponsorship + re-quoted gas into the
2073
+ * caller's `partialUserOp` skeleton.
2074
+ * 2. Compute the EIP-712 userOpHash + the typed-data payload (in
2075
+ * JSON-safe form for HTTP transport).
2076
+ * 3. (Optional) Repeat for the `partialUserOpFallback` skeleton with
2077
+ * no paymaster fields — produces a separate hash + typed-data so
2078
+ * the client can re-sign if it falls back.
2079
+ * 4. Persist a single store entry containing BOTH callData variants
2080
+ * keyed by lockId. `serializeEntryToJsonRpc` reads the `variant`
2081
+ * param at submit time.
2082
+ *
2083
+ * Replaces ~100 LoC of glue per scenario in issuer controllers.
2084
+ */
2085
+ declare function prepareMobileUserOp(params: PrepareMobileUserOpParams): Promise<PrepareMobileUserOpResult>;
2086
+
1817
2087
  interface IssuerRegistryRecord {
1818
2088
  issuerAddress: Address;
1819
2089
  signerAddress: Address;
@@ -1907,4 +2177,4 @@ declare class IssuerStateValidator {
1907
2177
  /** SDK package version — bumped on every release */
1908
2178
  declare const PAFI_ISSUER_SDK_VERSION = "0.4.0";
1909
2179
 
1910
- export { type ApiClaimRequest, type ApiClaimResponse, type ApiConfigResponse, type ApiGasFeeResponse, type ApiLoginRequest, type ApiLoginResponse, type ApiNonceResponse, type ApiPoolsRequest, type ApiPoolsResponse, type ApiRedeemRequest, type ApiRedeemResponse, type ApiTopUpRequest, type ApiTopUpResponse, type ApiUserRequest, type ApiUserResponse, type AuthContext, AuthError, type AuthErrorCode, AuthService, type AuthServiceConfig, BalanceAggregator, type BalanceAggregatorConfig, type BurnEvent, BurnIndexer, type BurnIndexerConfig, type CombinedBalance, DefaultPolicyEngine, type DefaultPolicyEngineOptions, FeeManager, type FeeManagerConfig, type IIndexerCursorStore, type IPendingUserOpStore, type IPointLedger, type IPolicyEngine, type ISessionStore, InMemoryCursorStore, IssuerApiHandlers, type IssuerApiHandlersConfig, type IssuerRegistryRecord, type IssuerService, type IssuerServiceConfig, IssuerStateError, IssuerStateValidator, type LockedMintRequest, type LoginResult, MemorySessionStore, type MemorySessionStoreOptions, type MintEvent, type MintingStatus, type NativePtQuoterConfig, NonceManager, PAFI_ISSUER_SDK_VERSION, PTRedeemError, PTRedeemHandler, type PTRedeemHandlerConfig, type PTRedeemRequest, type PTRedeemResponse, PafiBackendClient, type PafiBackendConfig, PafiBackendError, type PafiBackendErrorCode, type PendingUserOpEntry, PointIndexer, type PointIndexerConfig, type PolicyDecision, type PolicyEvalRequest, type PoolsProvider, type PreValidateMintResult, type PrepareBurnDirectParams, type PrepareBurnParams, type PrepareBurnWithSigParams, type PrepareMintParams, RelayError, type RelayErrorCode, RelayService, type RelayUserOpRequest, type RelayUserOpResponse, type RetryConfig, type Session, type SponsorshipRequest, type SponsorshipResponse, type SponsorshipTarget, type SponsorshipUserOp, type SubgraphNativeUsdtQuoterConfig, type SubgraphPoolsProviderConfig, TopUpRedemptionError, TopUpRedemptionHandler, type TopUpRedemptionHandlerConfig, type TopUpRedemptionRequest, type TopUpRedemptionResponse, authenticateRequest, createIssuerService, createNativePtQuoter, createSubgraphNativeUsdtQuoter, createSubgraphPoolsProvider, serializeEntryToJsonRpc };
2180
+ export { type ApiClaimRequest, type ApiClaimResponse, type ApiConfigResponse, type ApiGasFeeResponse, type ApiLoginRequest, type ApiLoginResponse, type ApiNonceResponse, type ApiPoolsRequest, type ApiPoolsResponse, type ApiRedeemRequest, type ApiRedeemResponse, type ApiTopUpRequest, type ApiTopUpResponse, type ApiUserRequest, type ApiUserResponse, type AuthContext, AuthError, type AuthErrorCode, AuthService, type AuthServiceConfig, BalanceAggregator, type BalanceAggregatorConfig, type BurnEvent, BurnIndexer, type BurnIndexerConfig, type BurnStatusParams, type BurnStatusResponse, type CombinedBalance, DefaultPolicyEngine, type DefaultPolicyEngineOptions, FeeManager, type FeeManagerConfig, type IIndexerCursorStore, type IPendingUserOpStore, type IPointLedger, type IPolicyEngine, type ISessionStore, InMemoryCursorStore, IssuerApiHandlers, type IssuerApiHandlersConfig, type IssuerRegistryRecord, type IssuerService, type IssuerServiceConfig, IssuerStateError, IssuerStateValidator, LockNotFoundError, type LockedMintRequest, type LoginResult, MemorySessionStore, type MemorySessionStoreOptions, type MintEvent, type MintStatusParams, type MintStatusResponse, type MintingStatus, type NativePtQuoterConfig, NonceManager, PAFI_ISSUER_SDK_VERSION, PTRedeemError, PTRedeemHandler, type PTRedeemHandlerConfig, type PTRedeemRequest, type PTRedeemResponse, PafiBackendClient, type PafiBackendConfig, PafiBackendError, type PafiBackendErrorCode, type PendingCredit, type PendingUserOpEntry, PointIndexer, type PointIndexerConfig, type PolicyDecision, type PolicyEvalRequest, type PoolsProvider, type PreValidateMintResult, type PrepareBurnDirectParams, type PrepareBurnParams, type PrepareBurnWithSigParams, type PrepareMintParams, type PrepareMobileUserOpParams, type PrepareMobileUserOpResult, type PreparedUserOp, RelayError, type RelayErrorCode, RelayService, type RelayUserOpRequest, type RelayUserOpResponse, type RetryConfig, type SerializedUserOpTypedData, type Session, type SponsorshipRequest, type SponsorshipResponse, type SponsorshipTarget, type SponsorshipUserOp, type SubgraphNativeUsdtQuoterConfig, type SubgraphPoolsProviderConfig, TopUpRedemptionError, TopUpRedemptionHandler, type TopUpRedemptionHandlerConfig, type TopUpRedemptionRequest, type TopUpRedemptionResponse, authenticateRequest, createIssuerService, createNativePtQuoter, createSubgraphNativeUsdtQuoter, createSubgraphPoolsProvider, handleClaimStatus, handleRedeemStatus, mergePaymasterFields, prepareMobileUserOp, serializeEntryToJsonRpc, serializeUserOpTypedData };