@pafi-dev/issuer 0.5.32 → 0.5.34
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.cjs +287 -7
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +462 -100
- package/dist/index.d.ts +462 -100
- package/dist/index.js +274 -1
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.d.ts
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, ENTRY_POINT_V08, 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,37 +1744,70 @@ declare class BalanceAggregator {
|
|
|
1511
1744
|
getCombinedBalanceMulti(user: Address, pointTokens: Address[]): Promise<Map<Address, CombinedBalance>>;
|
|
1512
1745
|
}
|
|
1513
1746
|
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1747
|
+
/**
|
|
1748
|
+
* Typed errors thrown by the helpers below — issuer controllers map
|
|
1749
|
+
* these to the appropriate HTTP status. We don't depend on @nestjs/common
|
|
1750
|
+
* here because the SDK is framework-agnostic; the consuming controller
|
|
1751
|
+
* wraps each one in its preferred exception class.
|
|
1752
|
+
*/
|
|
1753
|
+
declare class BundlerNotConfiguredError extends Error {
|
|
1754
|
+
readonly code = "BUNDLER_NOT_CONFIGURED";
|
|
1755
|
+
constructor();
|
|
1756
|
+
}
|
|
1757
|
+
declare class BundlerRejectedError extends Error {
|
|
1758
|
+
readonly code = "BUNDLER_REJECTED";
|
|
1759
|
+
readonly cause: unknown;
|
|
1760
|
+
constructor(message: string, cause: unknown);
|
|
1761
|
+
}
|
|
1762
|
+
interface RequestPaymasterParams {
|
|
1763
|
+
/** PAFI backend client. When `null` / `undefined` → returns `undefined`. */
|
|
1764
|
+
client: PafiBackendClient | null | undefined;
|
|
1765
|
+
chainId: number;
|
|
1766
|
+
scenario: string;
|
|
1767
|
+
/** UserOp skeleton — must have all gas + fee fields set. */
|
|
1768
|
+
userOp: {
|
|
1769
|
+
sender: Address;
|
|
1770
|
+
nonce: bigint;
|
|
1771
|
+
callData: Hex;
|
|
1772
|
+
callGasLimit: bigint;
|
|
1773
|
+
verificationGasLimit: bigint;
|
|
1774
|
+
preVerificationGas: bigint;
|
|
1775
|
+
maxFeePerGas: bigint;
|
|
1776
|
+
maxPriorityFeePerGas: bigint;
|
|
1777
|
+
};
|
|
1778
|
+
/** Target contract (typically the PointToken). */
|
|
1779
|
+
pointTokenAddress: Address;
|
|
1780
|
+
/**
|
|
1781
|
+
* Function name to surface in audit / paymaster context. Defaults to
|
|
1782
|
+
* a per-scenario sensible value (`mint` / `burn` / `swap` / generic
|
|
1783
|
+
* scenario name).
|
|
1784
|
+
*/
|
|
1785
|
+
functionName?: string;
|
|
1786
|
+
/** Optional logger for the "sponsorship declined" warning. */
|
|
1787
|
+
onWarning?: (msg: string) => void;
|
|
1540
1788
|
}
|
|
1541
|
-
|
|
1542
|
-
|
|
1789
|
+
/**
|
|
1790
|
+
* Thin wrapper around `PafiBackendClient.requestSponsorship` with the
|
|
1791
|
+
* "non-fatal on failure" semantics every issuer wants:
|
|
1792
|
+
*
|
|
1793
|
+
* - When the client is missing → returns `undefined` (the caller falls
|
|
1794
|
+
* back to a self-funded UserOp).
|
|
1795
|
+
* - When the network call throws OR PAFI declines (rate limit, intent
|
|
1796
|
+
* rejection, paymaster outage) → returns `undefined` after logging,
|
|
1797
|
+
* so the controller doesn't hard-fail. The caller's
|
|
1798
|
+
* `prepareMobileUserOp` / `mergePaymasterFields` will gracefully
|
|
1799
|
+
* produce the unsponsored variant.
|
|
1800
|
+
*
|
|
1801
|
+
* Replaces ~30 LoC of try/catch + scenario-to-function mapping every
|
|
1802
|
+
* issuer would copy.
|
|
1803
|
+
*/
|
|
1804
|
+
declare function requestPaymaster(params: RequestPaymasterParams): Promise<Awaited<ReturnType<PafiBackendClient["requestSponsorship"]>> | undefined>;
|
|
1805
|
+
interface RelayUserOpParams {
|
|
1806
|
+
client: PafiBackendClient | null | undefined;
|
|
1807
|
+
/** EntryPoint address — typically `ENTRY_POINT_V08` from core. */
|
|
1808
|
+
entryPoint: typeof ENTRY_POINT_V08 | string;
|
|
1543
1809
|
userOp: Record<string, string | null>;
|
|
1544
|
-
|
|
1810
|
+
/** EIP-7702 authorization (delegation UserOps only). */
|
|
1545
1811
|
eip7702Auth?: {
|
|
1546
1812
|
chainId: string;
|
|
1547
1813
|
address: string;
|
|
@@ -1551,76 +1817,24 @@ interface RelayUserOpRequest {
|
|
|
1551
1817
|
yParity: string;
|
|
1552
1818
|
};
|
|
1553
1819
|
}
|
|
1554
|
-
|
|
1820
|
+
/**
|
|
1821
|
+
* Submit a serialized UserOp to the Pimlico bundler via PAFI's
|
|
1822
|
+
* sponsor-relayer. Handles the "client missing" / "bundler rejected"
|
|
1823
|
+
* branches as typed errors so the controller can map to HTTP cleanly.
|
|
1824
|
+
*
|
|
1825
|
+
* Every issuer mobile flow has this exact wrapper — moved into SDK
|
|
1826
|
+
* to drop ~30 LoC of try/catch + error-shape boilerplate per
|
|
1827
|
+
* controller.
|
|
1828
|
+
*
|
|
1829
|
+
* Throws:
|
|
1830
|
+
* - `BundlerNotConfiguredError` — caller didn't configure
|
|
1831
|
+
* `PafiBackendClient`. Map to 503.
|
|
1832
|
+
* - `BundlerRejectedError` — bundler returned an error. Map to 422
|
|
1833
|
+
* (the FE can show the reason — usually `AA21` / `AA34` / etc.).
|
|
1834
|
+
*/
|
|
1835
|
+
declare function relayUserOp(params: RelayUserOpParams): Promise<{
|
|
1555
1836
|
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
|
-
}
|
|
1837
|
+
}>;
|
|
1624
1838
|
|
|
1625
1839
|
/**
|
|
1626
1840
|
* Top-level configuration for `createIssuerService`.
|
|
@@ -1814,6 +2028,154 @@ interface IPendingUserOpStore {
|
|
|
1814
2028
|
*/
|
|
1815
2029
|
declare function serializeEntryToJsonRpc(entry: PendingUserOpEntry, signature: Hex, variant?: "sponsored" | "fallback"): Record<string, string | null>;
|
|
1816
2030
|
|
|
2031
|
+
/**
|
|
2032
|
+
* Re-shape `UserOpTypedData` so all `bigint` fields become hex strings —
|
|
2033
|
+
* required for JSON transport over HTTP. Mirrors the inverse of what
|
|
2034
|
+
* `walletClient.signTypedData` accepts on the client (it auto-coerces hex
|
|
2035
|
+
* strings back to bigints for `uint256` fields).
|
|
2036
|
+
*/
|
|
2037
|
+
type SerializedUserOpTypedData = {
|
|
2038
|
+
domain: UserOpTypedData["domain"];
|
|
2039
|
+
types: UserOpTypedData["types"];
|
|
2040
|
+
primaryType: UserOpTypedData["primaryType"];
|
|
2041
|
+
message: {
|
|
2042
|
+
sender: Address;
|
|
2043
|
+
nonce: Hex;
|
|
2044
|
+
initCode: Hex;
|
|
2045
|
+
callData: Hex;
|
|
2046
|
+
accountGasLimits: Hex;
|
|
2047
|
+
preVerificationGas: Hex;
|
|
2048
|
+
gasFees: Hex;
|
|
2049
|
+
paymasterAndData: Hex;
|
|
2050
|
+
};
|
|
2051
|
+
};
|
|
2052
|
+
/**
|
|
2053
|
+
* Convert a `UserOpTypedData` payload into the JSON-safe wire form
|
|
2054
|
+
* (bigint → hex string). The mobile client passes this directly to
|
|
2055
|
+
* `eth_signTypedData_v4` / viem's `signTypedData`.
|
|
2056
|
+
*/
|
|
2057
|
+
declare function serializeUserOpTypedData(td: UserOpTypedData): SerializedUserOpTypedData;
|
|
2058
|
+
/**
|
|
2059
|
+
* Merge Pimlico's paymaster-sponsorship response into a UserOp
|
|
2060
|
+
* skeleton, applying only fields that are actually defined.
|
|
2061
|
+
*
|
|
2062
|
+
* `pm_sponsorUserOperation` returns:
|
|
2063
|
+
* - `paymaster` / `paymasterData` — required for the sponsored sig
|
|
2064
|
+
* - `paymasterVerificationGasLimit` / `paymasterPostOpGasLimit`
|
|
2065
|
+
* - **re-estimated** `callGasLimit` / `verificationGasLimit` /
|
|
2066
|
+
* `preVerificationGas` — the paymaster signature is computed over
|
|
2067
|
+
* these new values
|
|
2068
|
+
* - **bundler-required** `maxFeePerGas` / `maxPriorityFeePerGas` —
|
|
2069
|
+
* Base RPC's `eth_feeHistory` underestimates, bundler rejects
|
|
2070
|
+
*
|
|
2071
|
+
* Callers MUST re-merge ALL of these into the userOp BEFORE computing
|
|
2072
|
+
* the EIP-712 userOpHash — otherwise both the paymaster signature
|
|
2073
|
+
* (AA34) and the user signature (AA24, recovered against a different
|
|
2074
|
+
* hash) fail at validation.
|
|
2075
|
+
*
|
|
2076
|
+
* Skips fields that are undefined so legacy paymaster responses
|
|
2077
|
+
* (without re-estimated gas) don't accidentally zero out the original
|
|
2078
|
+
* estimates.
|
|
2079
|
+
*/
|
|
2080
|
+
declare function mergePaymasterFields<T extends object>(userOp: T, paymasterFields: {
|
|
2081
|
+
paymaster: Address;
|
|
2082
|
+
paymasterData: Hex;
|
|
2083
|
+
paymasterVerificationGasLimit: bigint;
|
|
2084
|
+
paymasterPostOpGasLimit: bigint;
|
|
2085
|
+
callGasLimit?: bigint;
|
|
2086
|
+
verificationGasLimit?: bigint;
|
|
2087
|
+
preVerificationGas?: bigint;
|
|
2088
|
+
maxFeePerGas?: bigint;
|
|
2089
|
+
maxPriorityFeePerGas?: bigint;
|
|
2090
|
+
} | undefined): T;
|
|
2091
|
+
interface PreparedUserOp {
|
|
2092
|
+
/** The bundler-ready UserOp (with paymaster + Pimlico-quoted gas). */
|
|
2093
|
+
userOp: PartialUserOperation & {
|
|
2094
|
+
maxFeePerGas: bigint;
|
|
2095
|
+
maxPriorityFeePerGas: bigint;
|
|
2096
|
+
paymaster?: Address;
|
|
2097
|
+
paymasterData?: Hex;
|
|
2098
|
+
paymasterVerificationGasLimit?: bigint;
|
|
2099
|
+
paymasterPostOpGasLimit?: bigint;
|
|
2100
|
+
};
|
|
2101
|
+
/** Hex-encoded EIP-712 digest. Equals `EntryPoint.getUserOpHash`. */
|
|
2102
|
+
userOpHash: Hex;
|
|
2103
|
+
/** Typed-data payload — pass directly to `eth_signTypedData_v4`. */
|
|
2104
|
+
typedData: SerializedUserOpTypedData;
|
|
2105
|
+
}
|
|
2106
|
+
interface PrepareMobileUserOpParams {
|
|
2107
|
+
/** Lock id (issuer-generated) keying both store entry + ledger row. */
|
|
2108
|
+
lockId: string;
|
|
2109
|
+
/**
|
|
2110
|
+
* Sponsored variant — built with the PT operator-fee transfer
|
|
2111
|
+
* included. SDK or caller should set `partialUserOp.maxFeePerGas` /
|
|
2112
|
+
* `maxPriorityFeePerGas` from `provider.estimateFeesPerGas()` before
|
|
2113
|
+
* calling — they get overridden by Pimlico's quote anyway, but
|
|
2114
|
+
* they must be valid bigints for the merge.
|
|
2115
|
+
*/
|
|
2116
|
+
partialUserOp: PartialUserOperation & {
|
|
2117
|
+
maxFeePerGas: bigint;
|
|
2118
|
+
maxPriorityFeePerGas: bigint;
|
|
2119
|
+
};
|
|
2120
|
+
/**
|
|
2121
|
+
* Optional fee-stripped fallback variant — built with `gasFeePt: 0n`
|
|
2122
|
+
* (no PT operator-fee transfer). Submitted when paymaster refuses
|
|
2123
|
+
* sponsorship and the user pays ETH gas directly.
|
|
2124
|
+
*/
|
|
2125
|
+
partialUserOpFallback?: PartialUserOperation & {
|
|
2126
|
+
maxFeePerGas?: bigint;
|
|
2127
|
+
maxPriorityFeePerGas?: bigint;
|
|
2128
|
+
};
|
|
2129
|
+
/** Paymaster sponsorship response, or `undefined` if PAFI declined. */
|
|
2130
|
+
paymasterFields?: {
|
|
2131
|
+
paymaster: Address;
|
|
2132
|
+
paymasterData: Hex;
|
|
2133
|
+
paymasterVerificationGasLimit: bigint;
|
|
2134
|
+
paymasterPostOpGasLimit: bigint;
|
|
2135
|
+
callGasLimit?: bigint;
|
|
2136
|
+
verificationGasLimit?: bigint;
|
|
2137
|
+
preVerificationGas?: bigint;
|
|
2138
|
+
maxFeePerGas?: bigint;
|
|
2139
|
+
maxPriorityFeePerGas?: bigint;
|
|
2140
|
+
};
|
|
2141
|
+
chainId: number;
|
|
2142
|
+
/** Pending-userop store implementation (Redis/Postgres/Memory). */
|
|
2143
|
+
store: IPendingUserOpStore;
|
|
2144
|
+
/** TTL the store entry should outlive — typically the MintRequest deadline. */
|
|
2145
|
+
ttlSeconds: number;
|
|
2146
|
+
}
|
|
2147
|
+
interface PrepareMobileUserOpResult {
|
|
2148
|
+
sponsored: PreparedUserOp;
|
|
2149
|
+
/**
|
|
2150
|
+
* Set when `partialUserOpFallback` was supplied AND the PT fee was
|
|
2151
|
+
* non-zero (i.e. sponsored ≠ fallback). Mobile client picks which
|
|
2152
|
+
* variant to sign + submit; SDK's `serializeEntryToJsonRpc` reads
|
|
2153
|
+
* the `variant` flag to dispatch.
|
|
2154
|
+
*/
|
|
2155
|
+
fallback?: PreparedUserOp;
|
|
2156
|
+
/** What got persisted into the pending-userop store. */
|
|
2157
|
+
entry: PendingUserOpEntry;
|
|
2158
|
+
}
|
|
2159
|
+
/**
|
|
2160
|
+
* Build the sponsored UserOp + (optional) fee-stripped fallback for the
|
|
2161
|
+
* mobile prepare/submit flow.
|
|
2162
|
+
*
|
|
2163
|
+
* What this does, end-to-end:
|
|
2164
|
+
* 1. Merge Pimlico's paymaster sponsorship + re-quoted gas into the
|
|
2165
|
+
* caller's `partialUserOp` skeleton.
|
|
2166
|
+
* 2. Compute the EIP-712 userOpHash + the typed-data payload (in
|
|
2167
|
+
* JSON-safe form for HTTP transport).
|
|
2168
|
+
* 3. (Optional) Repeat for the `partialUserOpFallback` skeleton with
|
|
2169
|
+
* no paymaster fields — produces a separate hash + typed-data so
|
|
2170
|
+
* the client can re-sign if it falls back.
|
|
2171
|
+
* 4. Persist a single store entry containing BOTH callData variants
|
|
2172
|
+
* keyed by lockId. `serializeEntryToJsonRpc` reads the `variant`
|
|
2173
|
+
* param at submit time.
|
|
2174
|
+
*
|
|
2175
|
+
* Replaces ~100 LoC of glue per scenario in issuer controllers.
|
|
2176
|
+
*/
|
|
2177
|
+
declare function prepareMobileUserOp(params: PrepareMobileUserOpParams): Promise<PrepareMobileUserOpResult>;
|
|
2178
|
+
|
|
1817
2179
|
interface IssuerRegistryRecord {
|
|
1818
2180
|
issuerAddress: Address;
|
|
1819
2181
|
signerAddress: Address;
|
|
@@ -1907,4 +2269,4 @@ declare class IssuerStateValidator {
|
|
|
1907
2269
|
/** SDK package version — bumped on every release */
|
|
1908
2270
|
declare const PAFI_ISSUER_SDK_VERSION = "0.4.0";
|
|
1909
2271
|
|
|
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 };
|
|
2272
|
+
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, BundlerNotConfiguredError, BundlerRejectedError, 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 RelayUserOpParams, type RelayUserOpRequest, type RelayUserOpResponse, type RequestPaymasterParams, 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, relayUserOp, requestPaymaster, serializeEntryToJsonRpc, serializeUserOpTypedData };
|