@pafi-dev/issuer 0.5.34 → 0.5.35
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 +698 -244
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +929 -614
- package/dist/index.d.ts +929 -614
- package/dist/index.js +698 -232
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
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,
|
|
2
|
+
import { PointTokenDomainConfig, PartialUserOperation, BurnRequest, PoolKey, UserOpTypedData, decodeBatchExecuteCalls, BROKER_HASHES, ENTRY_POINT_V08 } from '@pafi-dev/core';
|
|
3
3
|
export { PAFI_SUBGRAPH_URL } from '@pafi-dev/core';
|
|
4
4
|
|
|
5
5
|
/**
|
|
@@ -1528,745 +1528,1060 @@ declare function handleClaimStatus(params: MintStatusParams): Promise<MintStatus
|
|
|
1528
1528
|
declare function handleRedeemStatus(params: BurnStatusParams): Promise<BurnStatusResponse>;
|
|
1529
1529
|
|
|
1530
1530
|
/**
|
|
1531
|
-
*
|
|
1531
|
+
* A pending UserOp serialized for persistent storage (Redis, Postgres, memory).
|
|
1532
|
+
*
|
|
1533
|
+
* All bigint fields are stored as decimal strings so the entry can be
|
|
1534
|
+
* JSON-serialized without precision loss. Convert back to bigint before
|
|
1535
|
+
* calling `computeUserOpHash` or `serializeUserOpToJsonRpc`.
|
|
1532
1536
|
*/
|
|
1533
|
-
interface
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
fetchImpl?: typeof fetch;
|
|
1537
|
+
interface PendingUserOpEntry {
|
|
1538
|
+
sender: Address;
|
|
1539
|
+
nonce: string;
|
|
1540
|
+
callData: Hex;
|
|
1541
|
+
callGasLimit: string;
|
|
1542
|
+
verificationGasLimit: string;
|
|
1543
|
+
preVerificationGas: string;
|
|
1544
|
+
maxFeePerGas: string;
|
|
1545
|
+
maxPriorityFeePerGas: string;
|
|
1546
|
+
paymaster?: Address;
|
|
1547
|
+
paymasterVerificationGasLimit?: string;
|
|
1548
|
+
paymasterPostOpGasLimit?: string;
|
|
1549
|
+
paymasterData?: Hex;
|
|
1550
|
+
chainId: number;
|
|
1551
|
+
/** Hex-encoded userOpHash — the value the user signed via personal_sign. */
|
|
1552
|
+
userOpHash: Hex;
|
|
1550
1553
|
/**
|
|
1551
|
-
*
|
|
1554
|
+
* Fee-stripped fallback variant. Set by `/claim/prepare` and
|
|
1555
|
+
* `/redeem/prepare` when a PT operator fee is configured AND the
|
|
1556
|
+
* paymaster sponsorship attached successfully — i.e. the user might
|
|
1557
|
+
* still want to submit without paymaster (paying ETH gas), and in
|
|
1558
|
+
* that case shouldn't be charged the PT fee. `/claim/submit` reads
|
|
1559
|
+
* this branch when its request body specifies
|
|
1560
|
+
* `variant: "fallback"`.
|
|
1561
|
+
*
|
|
1562
|
+
* Has a different `callData` (no PT.transfer prepended) and
|
|
1563
|
+
* therefore a different `userOpHash`. Paymaster fields are NOT
|
|
1564
|
+
* present — the fallback is by definition unsponsored.
|
|
1552
1565
|
*/
|
|
1553
|
-
|
|
1566
|
+
fallback?: {
|
|
1567
|
+
callData: Hex;
|
|
1568
|
+
callGasLimit: string;
|
|
1569
|
+
verificationGasLimit: string;
|
|
1570
|
+
preVerificationGas: string;
|
|
1571
|
+
userOpHash: Hex;
|
|
1572
|
+
};
|
|
1554
1573
|
}
|
|
1555
1574
|
/**
|
|
1556
|
-
*
|
|
1557
|
-
*
|
|
1558
|
-
* Queries the `pafiTokens` entity for the given `pointTokenAddress`,
|
|
1559
|
-
* reads its linked `Pool`, and returns a single-element `PoolKey[]`.
|
|
1560
|
-
* Multiple pools per token would require a subgraph schema change.
|
|
1561
|
-
*
|
|
1562
|
-
* The result is cached in-process with a short TTL (default 30s). Pool
|
|
1563
|
-
* discovery is near-static so this avoids hammering the subgraph without
|
|
1564
|
-
* blocking config changes for long.
|
|
1565
|
-
*
|
|
1566
|
-
* Returns `{ pools: [] }` if:
|
|
1567
|
-
* - the token is not registered on PAFI yet (no PafiToken entity)
|
|
1568
|
-
* - the token is registered but its pool has not been initialised
|
|
1569
|
-
* - the subgraph is unreachable or returns an error (logs to console,
|
|
1570
|
-
* does not throw — callers should handle empty pool list gracefully)
|
|
1575
|
+
* Storage backend for pending UserOps in the mobile prepare/submit pattern.
|
|
1571
1576
|
*
|
|
1572
|
-
*
|
|
1573
|
-
*
|
|
1577
|
+
* Implement this interface and wire it into your issuer backend:
|
|
1578
|
+
* - `save()` — called by `POST /claim/prepare` and `POST /redeem/prepare`
|
|
1579
|
+
* - `get()` — called by `POST /claim/submit` and `POST /redeem/submit`
|
|
1580
|
+
* - `delete()` — called after successful submit or explicit cancellation
|
|
1574
1581
|
*
|
|
1575
|
-
*
|
|
1576
|
-
*
|
|
1577
|
-
|
|
1582
|
+
* The default implementation in the gg56 boilerplate uses Redis with
|
|
1583
|
+
* a short TTL matching the MintRequest / BurnRequest deadline.
|
|
1584
|
+
*/
|
|
1585
|
+
interface IPendingUserOpStore {
|
|
1586
|
+
save(lockId: string, entry: PendingUserOpEntry, ttlSeconds: number): Promise<void>;
|
|
1587
|
+
get(lockId: string): Promise<PendingUserOpEntry | null>;
|
|
1588
|
+
delete(lockId: string): Promise<void>;
|
|
1589
|
+
}
|
|
1590
|
+
|
|
1591
|
+
/**
|
|
1592
|
+
* Convert a stored `PendingUserOpEntry` (decimal-string fields) plus a
|
|
1593
|
+
* signature into the JSON-RPC wire format for `eth_sendUserOperation`.
|
|
1578
1594
|
*
|
|
1579
|
-
*
|
|
1580
|
-
*
|
|
1581
|
-
* poolsProvider: createSubgraphPoolsProvider({
|
|
1582
|
-
* subgraphUrl: "https://graph.pacificfinance.org/subgraphs/name/pafi",
|
|
1583
|
-
* }),
|
|
1584
|
-
* });
|
|
1585
|
-
* ```
|
|
1595
|
+
* Bridges the gap between the serialized storage format (decimal strings,
|
|
1596
|
+
* safe for JSON/Redis) and `serializeUserOpToJsonRpc` which expects bigints.
|
|
1586
1597
|
*/
|
|
1587
|
-
declare function
|
|
1598
|
+
declare function serializeEntryToJsonRpc(entry: PendingUserOpEntry, signature: Hex, variant?: "sponsored" | "fallback"): Record<string, string | null>;
|
|
1588
1599
|
|
|
1589
1600
|
/**
|
|
1590
|
-
*
|
|
1601
|
+
* Re-shape `UserOpTypedData` so all `bigint` fields become hex strings —
|
|
1602
|
+
* required for JSON transport over HTTP. Mirrors the inverse of what
|
|
1603
|
+
* `walletClient.signTypedData` accepts on the client (it auto-coerces hex
|
|
1604
|
+
* strings back to bigints for `uint256` fields).
|
|
1591
1605
|
*/
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
* MATIC on Polygon). Default: 18.
|
|
1608
|
-
*/
|
|
1609
|
-
nativeDecimals?: number;
|
|
1610
|
-
/**
|
|
1611
|
-
* Cache TTL in milliseconds. ETH price drifts slowly relative to gas
|
|
1612
|
-
* estimation needs — a 30s cache keeps fees stable across bursts of
|
|
1613
|
-
* requests without letting them go stale during volatile markets.
|
|
1614
|
-
* Set to 0 to disable caching. Default: 30_000.
|
|
1615
|
-
*/
|
|
1616
|
-
cacheTtlMs?: number;
|
|
1617
|
-
/**
|
|
1618
|
-
* Fallback price (USDT per native token, human-readable float) used
|
|
1619
|
-
* when the subgraph is unreachable. This keeps the backend operational
|
|
1620
|
-
* during subgraph outages rather than bricking cashouts. The fee will
|
|
1621
|
-
* be slightly off but the operator still gets paid. Default: 3000.
|
|
1622
|
-
*/
|
|
1623
|
-
fallbackEthPriceUsd?: number;
|
|
1624
|
-
/** Optional fetch override for test harnesses. */
|
|
1625
|
-
fetchImpl?: typeof fetch;
|
|
1626
|
-
/** Optional clock override for tests. */
|
|
1627
|
-
now?: () => number;
|
|
1628
|
-
}
|
|
1606
|
+
type SerializedUserOpTypedData = {
|
|
1607
|
+
domain: UserOpTypedData["domain"];
|
|
1608
|
+
types: UserOpTypedData["types"];
|
|
1609
|
+
primaryType: UserOpTypedData["primaryType"];
|
|
1610
|
+
message: {
|
|
1611
|
+
sender: Address;
|
|
1612
|
+
nonce: Hex;
|
|
1613
|
+
initCode: Hex;
|
|
1614
|
+
callData: Hex;
|
|
1615
|
+
accountGasLimits: Hex;
|
|
1616
|
+
preVerificationGas: Hex;
|
|
1617
|
+
gasFees: Hex;
|
|
1618
|
+
paymasterAndData: Hex;
|
|
1619
|
+
};
|
|
1620
|
+
};
|
|
1629
1621
|
/**
|
|
1630
|
-
*
|
|
1631
|
-
*
|
|
1632
|
-
* `
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
*
|
|
1637
|
-
*
|
|
1638
|
-
* Price precision is not critical — a 1-2% drift is acceptable since
|
|
1639
|
-
* the fee manager applies a `gasPremiumBps` buffer.
|
|
1622
|
+
* Convert a `UserOpTypedData` payload into the JSON-safe wire form
|
|
1623
|
+
* (bigint → hex string). The mobile client passes this directly to
|
|
1624
|
+
* `eth_signTypedData_v4` / viem's `signTypedData`.
|
|
1625
|
+
*/
|
|
1626
|
+
declare function serializeUserOpTypedData(td: UserOpTypedData): SerializedUserOpTypedData;
|
|
1627
|
+
/**
|
|
1628
|
+
* Merge Pimlico's paymaster-sponsorship response into a UserOp
|
|
1629
|
+
* skeleton, applying only fields that are actually defined.
|
|
1640
1630
|
*
|
|
1641
|
-
*
|
|
1642
|
-
*
|
|
1643
|
-
*
|
|
1631
|
+
* `pm_sponsorUserOperation` returns:
|
|
1632
|
+
* - `paymaster` / `paymasterData` — required for the sponsored sig
|
|
1633
|
+
* - `paymasterVerificationGasLimit` / `paymasterPostOpGasLimit`
|
|
1634
|
+
* - **re-estimated** `callGasLimit` / `verificationGasLimit` /
|
|
1635
|
+
* `preVerificationGas` — the paymaster signature is computed over
|
|
1636
|
+
* these new values
|
|
1637
|
+
* - **bundler-required** `maxFeePerGas` / `maxPriorityFeePerGas` —
|
|
1638
|
+
* Base RPC's `eth_feeHistory` underestimates, bundler rejects
|
|
1644
1639
|
*
|
|
1645
|
-
*
|
|
1646
|
-
*
|
|
1647
|
-
*
|
|
1640
|
+
* Callers MUST re-merge ALL of these into the userOp BEFORE computing
|
|
1641
|
+
* the EIP-712 userOpHash — otherwise both the paymaster signature
|
|
1642
|
+
* (AA34) and the user signature (AA24, recovered against a different
|
|
1643
|
+
* hash) fail at validation.
|
|
1648
1644
|
*
|
|
1649
|
-
*
|
|
1650
|
-
*
|
|
1651
|
-
*
|
|
1652
|
-
* quoteNativeToFee: createSubgraphNativeUsdtQuoter({
|
|
1653
|
-
* subgraphUrl: "https://graph.pacificfinance.org/subgraphs/name/pafi",
|
|
1654
|
-
* }),
|
|
1655
|
-
* },
|
|
1656
|
-
* });
|
|
1657
|
-
* ```
|
|
1645
|
+
* Skips fields that are undefined so legacy paymaster responses
|
|
1646
|
+
* (without re-estimated gas) don't accidentally zero out the original
|
|
1647
|
+
* estimates.
|
|
1658
1648
|
*/
|
|
1659
|
-
declare function
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
|
|
1677
|
-
|
|
1649
|
+
declare function mergePaymasterFields<T extends object>(userOp: T, paymasterFields: {
|
|
1650
|
+
paymaster: Address;
|
|
1651
|
+
paymasterData: Hex;
|
|
1652
|
+
paymasterVerificationGasLimit: bigint;
|
|
1653
|
+
paymasterPostOpGasLimit: bigint;
|
|
1654
|
+
callGasLimit?: bigint;
|
|
1655
|
+
verificationGasLimit?: bigint;
|
|
1656
|
+
preVerificationGas?: bigint;
|
|
1657
|
+
maxFeePerGas?: bigint;
|
|
1658
|
+
maxPriorityFeePerGas?: bigint;
|
|
1659
|
+
} | undefined): T;
|
|
1660
|
+
interface PreparedUserOp {
|
|
1661
|
+
/** The bundler-ready UserOp (with paymaster + Pimlico-quoted gas). */
|
|
1662
|
+
userOp: PartialUserOperation & {
|
|
1663
|
+
maxFeePerGas: bigint;
|
|
1664
|
+
maxPriorityFeePerGas: bigint;
|
|
1665
|
+
paymaster?: Address;
|
|
1666
|
+
paymasterData?: Hex;
|
|
1667
|
+
paymasterVerificationGasLimit?: bigint;
|
|
1668
|
+
paymasterPostOpGasLimit?: bigint;
|
|
1669
|
+
};
|
|
1670
|
+
/** Hex-encoded EIP-712 digest. Equals `EntryPoint.getUserOpHash`. */
|
|
1671
|
+
userOpHash: Hex;
|
|
1672
|
+
/** Typed-data payload — pass directly to `eth_signTypedData_v4`. */
|
|
1673
|
+
typedData: SerializedUserOpTypedData;
|
|
1678
1674
|
}
|
|
1679
|
-
|
|
1680
|
-
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
|
|
1675
|
+
interface PrepareMobileUserOpParams {
|
|
1676
|
+
/** Lock id (issuer-generated) keying both store entry + ledger row. */
|
|
1677
|
+
lockId: string;
|
|
1678
|
+
/**
|
|
1679
|
+
* Sponsored variant — built with the PT operator-fee transfer
|
|
1680
|
+
* included. SDK or caller should set `partialUserOp.maxFeePerGas` /
|
|
1681
|
+
* `maxPriorityFeePerGas` from `provider.estimateFeesPerGas()` before
|
|
1682
|
+
* calling — they get overridden by Pimlico's quote anyway, but
|
|
1683
|
+
* they must be valid bigints for the merge.
|
|
1684
|
+
*/
|
|
1685
|
+
partialUserOp: PartialUserOperation & {
|
|
1686
|
+
maxFeePerGas: bigint;
|
|
1687
|
+
maxPriorityFeePerGas: bigint;
|
|
1688
|
+
};
|
|
1689
|
+
/**
|
|
1690
|
+
* Optional fee-stripped fallback variant — built with `gasFeePt: 0n`
|
|
1691
|
+
* (no PT operator-fee transfer). Submitted when paymaster refuses
|
|
1692
|
+
* sponsorship and the user pays ETH gas directly.
|
|
1693
|
+
*/
|
|
1694
|
+
partialUserOpFallback?: PartialUserOperation & {
|
|
1695
|
+
maxFeePerGas?: bigint;
|
|
1696
|
+
maxPriorityFeePerGas?: bigint;
|
|
1697
|
+
};
|
|
1698
|
+
/** Paymaster sponsorship response, or `undefined` if PAFI declined. */
|
|
1699
|
+
paymasterFields?: {
|
|
1700
|
+
paymaster: Address;
|
|
1701
|
+
paymasterData: Hex;
|
|
1702
|
+
paymasterVerificationGasLimit: bigint;
|
|
1703
|
+
paymasterPostOpGasLimit: bigint;
|
|
1704
|
+
callGasLimit?: bigint;
|
|
1705
|
+
verificationGasLimit?: bigint;
|
|
1706
|
+
preVerificationGas?: bigint;
|
|
1707
|
+
maxFeePerGas?: bigint;
|
|
1708
|
+
maxPriorityFeePerGas?: bigint;
|
|
1709
|
+
};
|
|
1710
|
+
chainId: number;
|
|
1711
|
+
/** Pending-userop store implementation (Redis/Postgres/Memory). */
|
|
1712
|
+
store: IPendingUserOpStore;
|
|
1713
|
+
/** TTL the store entry should outlive — typically the MintRequest deadline. */
|
|
1714
|
+
ttlSeconds: number;
|
|
1715
|
+
}
|
|
1716
|
+
interface PrepareMobileUserOpResult {
|
|
1717
|
+
sponsored: PreparedUserOp;
|
|
1718
|
+
/**
|
|
1719
|
+
* Set when `partialUserOpFallback` was supplied AND the PT fee was
|
|
1720
|
+
* non-zero (i.e. sponsored ≠ fallback). Mobile client picks which
|
|
1721
|
+
* variant to sign + submit; SDK's `serializeEntryToJsonRpc` reads
|
|
1722
|
+
* the `variant` flag to dispatch.
|
|
1723
|
+
*/
|
|
1724
|
+
fallback?: PreparedUserOp;
|
|
1725
|
+
/** What got persisted into the pending-userop store. */
|
|
1726
|
+
entry: PendingUserOpEntry;
|
|
1727
|
+
}
|
|
1728
|
+
/**
|
|
1729
|
+
* Build the sponsored UserOp + (optional) fee-stripped fallback for the
|
|
1730
|
+
* mobile prepare/submit flow.
|
|
1687
1731
|
*
|
|
1688
|
-
*
|
|
1732
|
+
* What this does, end-to-end:
|
|
1733
|
+
* 1. Merge Pimlico's paymaster sponsorship + re-quoted gas into the
|
|
1734
|
+
* caller's `partialUserOp` skeleton.
|
|
1735
|
+
* 2. Compute the EIP-712 userOpHash + the typed-data payload (in
|
|
1736
|
+
* JSON-safe form for HTTP transport).
|
|
1737
|
+
* 3. (Optional) Repeat for the `partialUserOpFallback` skeleton with
|
|
1738
|
+
* no paymaster fields — produces a separate hash + typed-data so
|
|
1739
|
+
* the client can re-sign if it falls back.
|
|
1740
|
+
* 4. Persist a single store entry containing BOTH callData variants
|
|
1741
|
+
* keyed by lockId. `serializeEntryToJsonRpc` reads the `variant`
|
|
1742
|
+
* param at submit time.
|
|
1689
1743
|
*
|
|
1690
|
-
*
|
|
1691
|
-
* ```ts
|
|
1692
|
-
* fee: {
|
|
1693
|
-
* quoteNativeToFee: createNativePtQuoter({
|
|
1694
|
-
* provider,
|
|
1695
|
-
* pointTokenAddress: "0x...",
|
|
1696
|
-
* chainlinkFeedAddress: getContractAddresses(chainId).chainlinkEthUsd,
|
|
1697
|
-
* }),
|
|
1698
|
-
* }
|
|
1699
|
-
* ```
|
|
1744
|
+
* Replaces ~100 LoC of glue per scenario in issuer controllers.
|
|
1700
1745
|
*/
|
|
1701
|
-
declare function
|
|
1746
|
+
declare function prepareMobileUserOp(params: PrepareMobileUserOpParams): Promise<PrepareMobileUserOpResult>;
|
|
1702
1747
|
|
|
1703
1748
|
/**
|
|
1704
|
-
*
|
|
1749
|
+
* Mobile prepare/submit orchestrators — abstract the duplicate glue
|
|
1750
|
+
* between `/claim/prepare`+`/claim/submit` and `/redeem/prepare`+
|
|
1751
|
+
* `/redeem/submit`. Both share the same shape:
|
|
1705
1752
|
*
|
|
1706
|
-
*
|
|
1707
|
-
*
|
|
1708
|
-
*
|
|
1753
|
+
* prepare: fees + delegation check → paymaster → prepareMobileUserOp
|
|
1754
|
+
* submit: fetch entry → serialize+sign → relay → bind hash → delete
|
|
1755
|
+
*
|
|
1756
|
+
* Issuer controllers shrink to ~30 LoC each — wire the handler that
|
|
1757
|
+
* produces `partialUserOp[+ fallback]`, hand off to these.
|
|
1709
1758
|
*/
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
total: bigint;
|
|
1759
|
+
declare class PendingUserOpNotFoundError extends Error {
|
|
1760
|
+
readonly code = "PENDING_USEROP_NOT_FOUND";
|
|
1761
|
+
constructor(lockId: string);
|
|
1714
1762
|
}
|
|
1715
|
-
interface
|
|
1763
|
+
interface HandleMobilePrepareParams {
|
|
1764
|
+
/** User EOA — used for the delegation check. */
|
|
1765
|
+
userAddress: Address;
|
|
1766
|
+
chainId: number;
|
|
1767
|
+
/** Lock id (issuer-generated) keying both store entry + ledger row. */
|
|
1768
|
+
lockId: string;
|
|
1769
|
+
/**
|
|
1770
|
+
* Partial UserOp from the upstream handler (PTClaimHandler /
|
|
1771
|
+
* PTRedeemHandler). The orchestrator will top up `maxFeePerGas` /
|
|
1772
|
+
* `maxPriorityFeePerGas` from `provider.estimateFeesPerGas()` if the
|
|
1773
|
+
* fields aren't already set, then request paymaster sponsorship.
|
|
1774
|
+
*/
|
|
1775
|
+
partialUserOp: PartialUserOperation;
|
|
1776
|
+
/** Optional fee-stripped fallback variant. */
|
|
1777
|
+
partialUserOpFallback?: PartialUserOperation;
|
|
1778
|
+
/**
|
|
1779
|
+
* Scenario tag — passed to `requestSponsorship` so the relayer can
|
|
1780
|
+
* apply per-scenario L1 enforcement (`mint`, `burn`, etc.).
|
|
1781
|
+
*/
|
|
1782
|
+
scenario: string;
|
|
1783
|
+
/** Target contract for the paymaster intent. */
|
|
1784
|
+
pointTokenAddress: Address;
|
|
1785
|
+
/** TTL the store entry should outlive. Typically the lock duration in seconds. */
|
|
1786
|
+
ttlSeconds: number;
|
|
1787
|
+
store: IPendingUserOpStore;
|
|
1716
1788
|
provider: PublicClient;
|
|
1717
|
-
|
|
1789
|
+
/** Optional — when omitted, paymaster is skipped and `sponsored: false` is returned. */
|
|
1790
|
+
pafiBackendClient?: PafiBackendClient | null;
|
|
1791
|
+
onWarning?: (msg: string) => void;
|
|
1792
|
+
}
|
|
1793
|
+
interface HandleMobilePrepareResult extends PrepareMobileUserOpResult {
|
|
1794
|
+
/**
|
|
1795
|
+
* True when paymaster sponsorship was applied to the sponsored variant.
|
|
1796
|
+
* (Renamed from `sponsored` to avoid clashing with
|
|
1797
|
+
* `PrepareMobileUserOpResult.sponsored` which is the PreparedUserOp object.)
|
|
1798
|
+
*/
|
|
1799
|
+
isSponsored: boolean;
|
|
1800
|
+
/**
|
|
1801
|
+
* True when the user's EOA has no EIP-7702 delegation set on-chain.
|
|
1802
|
+
* The mobile client must run the `/delegate/*` flow first.
|
|
1803
|
+
*/
|
|
1804
|
+
needsDelegation: boolean;
|
|
1718
1805
|
}
|
|
1719
1806
|
/**
|
|
1720
|
-
*
|
|
1721
|
-
*
|
|
1807
|
+
* Build the mobile prepare response. End-to-end:
|
|
1808
|
+
*
|
|
1809
|
+
* 1. Pull `estimateFeesPerGas` + `getCode(user)` in parallel.
|
|
1810
|
+
* 2. Top up sponsored UserOp fees if the upstream handler left them
|
|
1811
|
+
* unset.
|
|
1812
|
+
* 3. `requestPaymaster` — non-fatal: if PAFI declines, the sponsored
|
|
1813
|
+
* variant still works, the FE just falls back to the unsponsored
|
|
1814
|
+
* response.
|
|
1815
|
+
* 4. `prepareMobileUserOp` — merge + hash + persist.
|
|
1816
|
+
*/
|
|
1817
|
+
declare function handleMobilePrepare(params: HandleMobilePrepareParams): Promise<HandleMobilePrepareResult>;
|
|
1818
|
+
interface HandleMobileSubmitParams {
|
|
1819
|
+
lockId: string;
|
|
1820
|
+
/** User signature over `userOpHash` (or `userOpHashFallback`). */
|
|
1821
|
+
signature: Hex;
|
|
1822
|
+
/** Which variant the user actually signed. Defaults to `'sponsored'`. */
|
|
1823
|
+
variant?: "sponsored" | "fallback";
|
|
1824
|
+
store: IPendingUserOpStore;
|
|
1825
|
+
/**
|
|
1826
|
+
* Bind the bundler-returned hash to the lock so `claim/redeem status`
|
|
1827
|
+
* can fall back to the bundler receipt when the indexer's
|
|
1828
|
+
* amount-based match races and resolves a sibling. Different ledgers
|
|
1829
|
+
* use different methods (`bindMintUserOpHash` vs `bindCreditUserOpHash`),
|
|
1830
|
+
* so the caller passes the correct one.
|
|
1831
|
+
*/
|
|
1832
|
+
bindUserOpHash: (lockId: string, userOpHash: Hex) => Promise<void>;
|
|
1833
|
+
pafiBackendClient?: PafiBackendClient | null;
|
|
1834
|
+
/** Defaults to `ENTRY_POINT_V08`. */
|
|
1835
|
+
entryPoint?: string;
|
|
1836
|
+
}
|
|
1837
|
+
/**
|
|
1838
|
+
* Submit a previously-prepared mobile UserOp to the bundler.
|
|
1722
1839
|
*
|
|
1723
|
-
*
|
|
1724
|
-
*
|
|
1725
|
-
*
|
|
1840
|
+
* Throws:
|
|
1841
|
+
* - `PendingUserOpNotFoundError` — entry expired or already submitted.
|
|
1842
|
+
* Map to 404.
|
|
1843
|
+
* - `BundlerNotConfiguredError` — `pafiBackendClient` missing. Map to 503.
|
|
1844
|
+
* - `BundlerRejectedError` — bundler rejected the UserOp. Map to 422.
|
|
1845
|
+
*/
|
|
1846
|
+
declare function handleMobileSubmit(params: HandleMobileSubmitParams): Promise<{
|
|
1847
|
+
userOpHash: Hex;
|
|
1848
|
+
}>;
|
|
1849
|
+
|
|
1850
|
+
interface IssuerRegistryRecord {
|
|
1851
|
+
issuerAddress: Address;
|
|
1852
|
+
signerAddress: Address;
|
|
1853
|
+
name: string;
|
|
1854
|
+
symbol: string;
|
|
1855
|
+
declaredTotalSupply: bigint;
|
|
1856
|
+
capBasisPoints: number;
|
|
1857
|
+
active: boolean;
|
|
1858
|
+
pointToken: Address;
|
|
1859
|
+
mintingOracle: Address;
|
|
1860
|
+
}
|
|
1861
|
+
interface PreValidateMintResult {
|
|
1862
|
+
/** Registry record read at pre-validation time. */
|
|
1863
|
+
issuer: IssuerRegistryRecord;
|
|
1864
|
+
/** Current on-chain PointToken.totalSupply(). */
|
|
1865
|
+
totalSupply: bigint;
|
|
1866
|
+
/** declaredTotalSupply × capBasisPoints / 10000. */
|
|
1867
|
+
hardCap: bigint;
|
|
1868
|
+
/** hardCap − totalSupply (clamped to 0). */
|
|
1869
|
+
remaining: bigint;
|
|
1870
|
+
}
|
|
1871
|
+
/**
|
|
1872
|
+
* Thrown by `IssuerStateValidator.preValidateMint()`.
|
|
1873
|
+
* `code` maps 1:1 to the HTTP error the issuer API surfaces to clients.
|
|
1874
|
+
*/
|
|
1875
|
+
declare class IssuerStateError extends Error {
|
|
1876
|
+
readonly code: "ISSUER_NOT_REGISTERED" | "ISSUER_INACTIVE" | "MINT_CAP_EXCEEDED";
|
|
1877
|
+
readonly details?: Record<string, unknown> | undefined;
|
|
1878
|
+
constructor(code: "ISSUER_NOT_REGISTERED" | "ISSUER_INACTIVE" | "MINT_CAP_EXCEEDED", message: string, details?: Record<string, unknown> | undefined);
|
|
1879
|
+
}
|
|
1880
|
+
|
|
1881
|
+
/**
|
|
1882
|
+
* Pure (framework-agnostic) validator for issuer state.
|
|
1726
1883
|
*
|
|
1727
|
-
*
|
|
1728
|
-
*
|
|
1884
|
+
* Reads IssuerRegistry + PointToken on-chain state and pre-validates
|
|
1885
|
+
* mint requests before the user submits a UserOp. Catching these
|
|
1886
|
+
* off-chain lets issuers fail fast with a clear error rather than
|
|
1887
|
+
* wasting gas on a revert.
|
|
1888
|
+
*
|
|
1889
|
+
* Caching:
|
|
1890
|
+
* - `PointToken.issuer()` — memoized for the process lifetime (immutable)
|
|
1891
|
+
* - Full state (registry + totalSupply) — 30s TTL per PointToken
|
|
1892
|
+
* - Burst calls while a fetch is in-flight share the same Promise
|
|
1893
|
+
* (thundering-herd protection)
|
|
1894
|
+
*
|
|
1895
|
+
* Usage in NestJS: wrap this in an `@Injectable()` service; pass
|
|
1896
|
+
* `PublicClient` and `registryAddress` from your DI container.
|
|
1729
1897
|
*/
|
|
1730
|
-
declare class
|
|
1898
|
+
declare class IssuerStateValidator {
|
|
1731
1899
|
private readonly provider;
|
|
1732
|
-
private readonly
|
|
1733
|
-
|
|
1900
|
+
private readonly registryAddress;
|
|
1901
|
+
private readonly pointTokenIssuerCache;
|
|
1902
|
+
private readonly stateCache;
|
|
1903
|
+
private readonly inflight;
|
|
1904
|
+
constructor(provider: PublicClient, registryAddress: Address);
|
|
1734
1905
|
/**
|
|
1735
|
-
*
|
|
1736
|
-
*
|
|
1906
|
+
* Convenience factory — reads `registryAddress` from the SDK
|
|
1907
|
+
* `CONTRACT_ADDRESSES` map for the given chain.
|
|
1737
1908
|
*/
|
|
1738
|
-
|
|
1909
|
+
static forChain(provider: PublicClient, chainId: number): IssuerStateValidator;
|
|
1739
1910
|
/**
|
|
1740
|
-
*
|
|
1741
|
-
*
|
|
1742
|
-
* (same casing as supplied — caller should normalize if needed).
|
|
1911
|
+
* Invalidate cached state for one PointToken, or everything if omitted.
|
|
1912
|
+
* Call after admin txs that change registry or cap settings.
|
|
1743
1913
|
*/
|
|
1744
|
-
|
|
1914
|
+
invalidate(pointToken?: Address): void;
|
|
1915
|
+
/**
|
|
1916
|
+
* Resolve `PointToken.issuer()` once per token and memoize.
|
|
1917
|
+
* The issuer field is set at `initialize()` and never changes.
|
|
1918
|
+
*/
|
|
1919
|
+
getIssuerAddressForPointToken(pointToken: Address): Promise<Address>;
|
|
1920
|
+
/**
|
|
1921
|
+
* Read registry record + totalSupply, with 30s cache and in-flight
|
|
1922
|
+
* deduplication. Does NOT throw on inactive/missing — returns raw state.
|
|
1923
|
+
*/
|
|
1924
|
+
getIssuerState(pointToken: Address): Promise<PreValidateMintResult>;
|
|
1925
|
+
/**
|
|
1926
|
+
* Validate that `amount` PT can be minted on `pointToken` right now.
|
|
1927
|
+
*
|
|
1928
|
+
* Throws `IssuerStateError` with:
|
|
1929
|
+
* - `ISSUER_NOT_REGISTERED` — registry has no record for this issuer
|
|
1930
|
+
* - `ISSUER_INACTIVE` — issuer.active is false
|
|
1931
|
+
* - `MINT_CAP_EXCEEDED` — totalSupply + amount would exceed hardCap
|
|
1932
|
+
*
|
|
1933
|
+
* Returns the fetched state on success so callers can log without a
|
|
1934
|
+
* second RPC round-trip.
|
|
1935
|
+
*/
|
|
1936
|
+
preValidateMint(pointToken: Address, amount: bigint): Promise<PreValidateMintResult>;
|
|
1937
|
+
private fetchIssuerState;
|
|
1745
1938
|
}
|
|
1746
1939
|
|
|
1940
|
+
type DecodedCall$2 = ReturnType<typeof decodeBatchExecuteCalls>[number];
|
|
1941
|
+
|
|
1747
1942
|
/**
|
|
1748
|
-
*
|
|
1749
|
-
*
|
|
1750
|
-
*
|
|
1751
|
-
*
|
|
1943
|
+
* v1.4 sig-gated mint handler — mirrors `PTRedeemHandler` on the mint side.
|
|
1944
|
+
*
|
|
1945
|
+
* Pre-validates against IssuerRegistry + on-chain totalSupply, locks the
|
|
1946
|
+
* off-chain balance, builds the sponsored UserOp (mint + PT fee
|
|
1947
|
+
* transfer) plus an optional fallback variant (mint only — for
|
|
1948
|
+
* paymaster-refused fallback).
|
|
1949
|
+
*
|
|
1950
|
+
* Caller fetches AA + mintRequest nonces (so issuers can plug in their
|
|
1951
|
+
* own composer — gg56 uses a timestamp-key 2D nonce). Caller layers
|
|
1952
|
+
* paymaster sponsorship + sponsorAuth on top of the returned UserOps.
|
|
1752
1953
|
*/
|
|
1753
|
-
declare class
|
|
1754
|
-
|
|
1755
|
-
|
|
1954
|
+
declare class PTClaimError extends Error {
|
|
1955
|
+
code: "INVALID_AMOUNT" | "VALIDATION_FAILED" | "BUILD_FAILED";
|
|
1956
|
+
details?: Record<string, unknown> | undefined;
|
|
1957
|
+
constructor(code: "INVALID_AMOUNT" | "VALIDATION_FAILED" | "BUILD_FAILED", message: string, details?: Record<string, unknown> | undefined);
|
|
1756
1958
|
}
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
1959
|
+
interface PTClaimHandlerConfig {
|
|
1960
|
+
ledger: IPointLedger;
|
|
1961
|
+
relayService: RelayService;
|
|
1962
|
+
provider: PublicClient;
|
|
1963
|
+
/** Issuer minter signer wallet — passed through to RelayService.prepareMint. */
|
|
1964
|
+
issuerSignerWallet: WalletClient;
|
|
1965
|
+
/**
|
|
1966
|
+
* EIP-712 domain `name` for `MintRequest`. Typically the PointToken
|
|
1967
|
+
* ERC-20 name. RelayService will set chainId + verifyingContract from
|
|
1968
|
+
* the request.
|
|
1969
|
+
*/
|
|
1970
|
+
pointTokenDomainName: string;
|
|
1971
|
+
/** Optional — when wired, used to estimate the PT gas-reimbursement fee. */
|
|
1972
|
+
feeService?: FeeManager;
|
|
1973
|
+
/** Optional — pre-validates issuer status + cap before locking balance. */
|
|
1974
|
+
issuerStateValidator?: IssuerStateValidator;
|
|
1975
|
+
/** How long the off-chain balance lock survives if the mint never lands. Default 15 min. */
|
|
1976
|
+
lockDurationMs?: number;
|
|
1977
|
+
/** How far ahead of `now` to set the MintRequest deadline. Default 15 min. */
|
|
1978
|
+
signatureDeadlineSeconds?: number;
|
|
1979
|
+
now?: () => number;
|
|
1761
1980
|
}
|
|
1762
|
-
interface
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
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). */
|
|
1981
|
+
interface PTClaimRequest {
|
|
1982
|
+
authenticatedAddress: Address;
|
|
1983
|
+
userAddress: Address;
|
|
1984
|
+
amount: bigint;
|
|
1779
1985
|
pointTokenAddress: Address;
|
|
1986
|
+
chainId: number;
|
|
1987
|
+
/** ERC-4337 account nonce for the user's EOA. */
|
|
1988
|
+
aaNonce: bigint;
|
|
1989
|
+
/** Current `mintRequestNonces[userAddress]` from PointToken. */
|
|
1990
|
+
mintRequestNonce: bigint;
|
|
1991
|
+
}
|
|
1992
|
+
interface PTClaimResponse {
|
|
1993
|
+
/** Sponsored UserOp — mint + PT fee transfer (when feeAmount > 0). */
|
|
1994
|
+
userOp: PartialUserOperation;
|
|
1780
1995
|
/**
|
|
1781
|
-
*
|
|
1782
|
-
*
|
|
1783
|
-
* scenario name).
|
|
1996
|
+
* Fallback UserOp — mint only, no PT fee transfer. Present only when
|
|
1997
|
+
* `feeAmount > 0`. User pays gas in ETH directly.
|
|
1784
1998
|
*/
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
|
|
1999
|
+
fallback?: PartialUserOperation;
|
|
2000
|
+
lockId: string;
|
|
2001
|
+
feeAmount: bigint;
|
|
2002
|
+
signatureDeadline: bigint;
|
|
2003
|
+
expiresInSeconds: number;
|
|
2004
|
+
/** Decoded calls for the sponsored UserOp (convenience for FE-submit path). */
|
|
2005
|
+
calls: DecodedCall$2[];
|
|
2006
|
+
/** Decoded calls for the fallback UserOp (when present). */
|
|
2007
|
+
callsFallback?: DecodedCall$2[];
|
|
1788
2008
|
}
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
|
|
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;
|
|
1809
|
-
userOp: Record<string, string | null>;
|
|
1810
|
-
/** EIP-7702 authorization (delegation UserOps only). */
|
|
1811
|
-
eip7702Auth?: {
|
|
1812
|
-
chainId: string;
|
|
1813
|
-
address: string;
|
|
1814
|
-
nonce: string;
|
|
1815
|
-
r: string;
|
|
1816
|
-
s: string;
|
|
1817
|
-
yParity: string;
|
|
1818
|
-
};
|
|
2009
|
+
declare class PTClaimHandler {
|
|
2010
|
+
private readonly cfg;
|
|
2011
|
+
constructor(config: PTClaimHandlerConfig);
|
|
2012
|
+
handle(request: PTClaimRequest): Promise<PTClaimResponse>;
|
|
1819
2013
|
}
|
|
2014
|
+
|
|
2015
|
+
type DecodedCall$1 = ReturnType<typeof decodeBatchExecuteCalls>[number];
|
|
2016
|
+
|
|
1820
2017
|
/**
|
|
1821
|
-
*
|
|
1822
|
-
* sponsor-relayer. Handles the "client missing" / "bundler rejected"
|
|
1823
|
-
* branches as typed errors so the controller can map to HTTP cleanly.
|
|
2018
|
+
* PT → USDT swap handler.
|
|
1824
2019
|
*
|
|
1825
|
-
*
|
|
1826
|
-
*
|
|
1827
|
-
*
|
|
2020
|
+
* Quotes via V4 on-chain Quoter (`findBestQuote`), applies slippage,
|
|
2021
|
+
* computes the PT gas-reimbursement fee from `FeeManager`, and builds
|
|
2022
|
+
* two UserOps:
|
|
1828
2023
|
*
|
|
1829
|
-
*
|
|
1830
|
-
*
|
|
1831
|
-
* `
|
|
1832
|
-
*
|
|
1833
|
-
*
|
|
2024
|
+
* - **sponsored** — swap (amountIn − fee) + transfer(fee, PAFI). User
|
|
2025
|
+
* holds exactly `amountIn` PT.
|
|
2026
|
+
* - **fallback** — swap full `amountIn`, no PT fee transfer. Built
|
|
2027
|
+
* only when `feeAmount > 0`. User pays gas in ETH directly.
|
|
2028
|
+
*
|
|
2029
|
+
* Re-quotes the sponsored path on `(amountIn − feeAmount)` because the
|
|
2030
|
+
* sponsored path actually swaps that much; the fallback uses the
|
|
2031
|
+
* original quote.
|
|
2032
|
+
*
|
|
2033
|
+
* Caller (controller) layers `sponsorAuth` on top of the returned
|
|
2034
|
+
* userOp. No off-chain ledger state is touched — swap is purely
|
|
2035
|
+
* on-chain.
|
|
1834
2036
|
*/
|
|
1835
|
-
declare
|
|
1836
|
-
|
|
1837
|
-
|
|
2037
|
+
declare class SwapError extends Error {
|
|
2038
|
+
code: "QUOTE_UNAVAILABLE" | "FEE_EXCEEDS_AMOUNT" | "INVALID_AMOUNT";
|
|
2039
|
+
constructor(code: "QUOTE_UNAVAILABLE" | "FEE_EXCEEDS_AMOUNT" | "INVALID_AMOUNT", message: string);
|
|
2040
|
+
}
|
|
2041
|
+
interface SwapHandlerConfig {
|
|
2042
|
+
provider: PublicClient;
|
|
2043
|
+
poolsProvider: PoolsProvider;
|
|
2044
|
+
/** Optional — when wired, used to estimate the PT gas-reimbursement fee. */
|
|
2045
|
+
feeService?: FeeManager;
|
|
2046
|
+
/**
|
|
2047
|
+
* Default slippage applied to the V4 quote when the request omits
|
|
2048
|
+
* `slippageBps`. 50 bps = 0.5%.
|
|
2049
|
+
*/
|
|
2050
|
+
defaultSlippageBps?: number;
|
|
2051
|
+
/** Default deadline window in seconds applied when not passed in request. Default 300. */
|
|
2052
|
+
defaultSwapDeadlineSeconds?: number;
|
|
2053
|
+
now?: () => number;
|
|
2054
|
+
}
|
|
2055
|
+
interface SwapRequest {
|
|
2056
|
+
userAddress: Address;
|
|
2057
|
+
chainId: number;
|
|
2058
|
+
pointTokenAddress: Address;
|
|
2059
|
+
amountIn: bigint;
|
|
2060
|
+
/** ERC-4337 account nonce for the user's EOA. */
|
|
2061
|
+
aaNonce: bigint;
|
|
2062
|
+
/** Optional override; falls back to `defaultSlippageBps`. */
|
|
2063
|
+
slippageBps?: number;
|
|
2064
|
+
/** Optional override; falls back to `now() + defaultSwapDeadlineSeconds`. */
|
|
2065
|
+
deadline?: bigint;
|
|
2066
|
+
}
|
|
2067
|
+
interface SwapResponse {
|
|
2068
|
+
/** Sponsored UserOp — swap (amountIn − fee) + PT.transfer(fee). */
|
|
2069
|
+
userOp: PartialUserOperation;
|
|
2070
|
+
/** Fallback UserOp — swap full amountIn, no PT fee transfer. Present only when fee > 0. */
|
|
2071
|
+
fallback?: PartialUserOperation;
|
|
2072
|
+
feeAmount: bigint;
|
|
2073
|
+
/** Quote for the sponsored path (after fee deduction). */
|
|
2074
|
+
estimatedUsdtOut: bigint;
|
|
2075
|
+
minAmountOut: bigint;
|
|
2076
|
+
/** Quote for the fallback path (full amountIn). Present only when fee > 0. */
|
|
2077
|
+
estimatedUsdtOutFallback?: bigint;
|
|
2078
|
+
minAmountOutFallback?: bigint;
|
|
2079
|
+
deadline: bigint;
|
|
2080
|
+
calls: DecodedCall$1[];
|
|
2081
|
+
callsFallback?: DecodedCall$1[];
|
|
2082
|
+
}
|
|
2083
|
+
declare class SwapHandler {
|
|
2084
|
+
private readonly cfg;
|
|
2085
|
+
constructor(config: SwapHandlerConfig);
|
|
2086
|
+
handle(request: SwapRequest): Promise<SwapResponse>;
|
|
2087
|
+
}
|
|
2088
|
+
|
|
2089
|
+
type DecodedCall = ReturnType<typeof decodeBatchExecuteCalls>[number];
|
|
1838
2090
|
|
|
1839
2091
|
/**
|
|
1840
|
-
*
|
|
2092
|
+
* Orderly perp-deposit handler — builds the sponsored + fallback
|
|
2093
|
+
* UserOps for the PAFI Relay path.
|
|
1841
2094
|
*
|
|
1842
|
-
*
|
|
1843
|
-
*
|
|
1844
|
-
*
|
|
1845
|
-
* frontend's responsibility via Bundler + Paymaster.
|
|
2095
|
+
* Resolves USDC + verifies the broker is whitelisted on the Vault,
|
|
2096
|
+
* quotes the Relay's USDC fee (covers LayerZero msg.value out of the
|
|
2097
|
+
* Relay's ETH reserve), then builds two UserOps:
|
|
1846
2098
|
*
|
|
1847
|
-
* **
|
|
1848
|
-
*
|
|
1849
|
-
*
|
|
1850
|
-
*
|
|
2099
|
+
* - **sponsored** — PT.transfer(fee, PAFI) + USDC.approve(relay,
|
|
2100
|
+
* total) + Relay.deposit(req). User reimburses gas in PT.
|
|
2101
|
+
* - **fallback** — USDC.approve + Relay.deposit only. User pays
|
|
2102
|
+
* ERC-4337 gas in ETH. Built only when `feeAmount > 0`.
|
|
2103
|
+
*
|
|
2104
|
+
* `maxFee` is set to `quote × 1.5` — slippage cap on the Relay's
|
|
2105
|
+
* USD-pricing during the inclusion window. If the actual fee at
|
|
2106
|
+
* execution exceeds maxFee the Relay reverts (`FeeExceedsMax`).
|
|
1851
2107
|
*/
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
pointTokenAddresses?: Address[];
|
|
1858
|
-
/**
|
|
1859
|
-
* Issuer-specific contract addresses merged into the `/config` response.
|
|
1860
|
-
* PAFI-owned addresses (batchExecutor, usdt, issuerRegistry, mintingOracle,
|
|
1861
|
-
* pafiHook) are auto-resolved from `getContractAddresses(chainId)` and
|
|
1862
|
-
* can be omitted. Only `pointToken` / `pointTokens` must be provided.
|
|
1863
|
-
*/
|
|
1864
|
-
contracts?: Pick<ApiConfigResponse["contracts"], "pointToken" | "pointTokens" | "relay">;
|
|
1865
|
-
/**
|
|
1866
|
-
* Shared `PublicClient` used for on-chain reads, simulation, indexer
|
|
1867
|
-
* polling, and gas-price lookups. Must be pointed at the target chain.
|
|
1868
|
-
*/
|
|
2108
|
+
declare class PerpDepositError extends Error {
|
|
2109
|
+
code: "PERP_DEPOSIT_UNAVAILABLE" | "BROKER_NOT_WHITELISTED" | "RELAY_FEE_EXCEEDS_AMOUNT" | "FEE_EXCEEDS_AMOUNT" | "INVALID_AMOUNT";
|
|
2110
|
+
constructor(code: "PERP_DEPOSIT_UNAVAILABLE" | "BROKER_NOT_WHITELISTED" | "RELAY_FEE_EXCEEDS_AMOUNT" | "FEE_EXCEEDS_AMOUNT" | "INVALID_AMOUNT", message: string);
|
|
2111
|
+
}
|
|
2112
|
+
interface PerpDepositHandlerConfig {
|
|
1869
2113
|
provider: PublicClient;
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
/** Passed straight to `jose` (`"24h"`, `"7d"`, …). Default `"24h"`. */
|
|
1875
|
-
jwtExpiresIn?: string;
|
|
1876
|
-
};
|
|
1877
|
-
/**
|
|
1878
|
-
* Off-chain point ledger — the source of truth for user balances and
|
|
1879
|
-
* in-flight minting locks. Every issuer provides their own database-backed
|
|
1880
|
-
* implementation (Postgres, Redis, etc.) that implements `IPointLedger`.
|
|
1881
|
-
* The SDK does not ship a production ledger; each issuer's data model and
|
|
1882
|
-
* infrastructure are different.
|
|
1883
|
-
*/
|
|
1884
|
-
ledger: IPointLedger;
|
|
2114
|
+
/** Optional — when wired, used to estimate the PT gas-reimbursement fee. */
|
|
2115
|
+
feeService?: FeeManager;
|
|
2116
|
+
/** PointToken address used for the sponsored PT.transfer. */
|
|
2117
|
+
pointTokenAddress: Address;
|
|
1885
2118
|
/**
|
|
1886
|
-
*
|
|
1887
|
-
*
|
|
2119
|
+
* Slippage premium applied on top of the Relay quote when computing
|
|
2120
|
+
* `maxFee`. Default 50% (factor 150). The Relay reverts if actual fee
|
|
2121
|
+
* exceeds `maxFee` so a generous cap reduces re-quote churn.
|
|
1888
2122
|
*/
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
|
|
2123
|
+
maxFeePremiumBps?: number;
|
|
2124
|
+
}
|
|
2125
|
+
interface PerpDepositRequest {
|
|
2126
|
+
userAddress: Address;
|
|
2127
|
+
chainId: number;
|
|
2128
|
+
amount: bigint;
|
|
2129
|
+
brokerId: keyof typeof BROKER_HASHES;
|
|
2130
|
+
/** ERC-4337 account nonce. */
|
|
2131
|
+
aaNonce: bigint;
|
|
2132
|
+
}
|
|
2133
|
+
interface PerpDepositResponse {
|
|
2134
|
+
userOp: PartialUserOperation;
|
|
2135
|
+
fallback?: PartialUserOperation;
|
|
2136
|
+
feeAmount: bigint;
|
|
2137
|
+
relayTokenFee: bigint;
|
|
2138
|
+
maxFee: bigint;
|
|
2139
|
+
netDeposit: bigint;
|
|
2140
|
+
accountId: `0x${string}`;
|
|
2141
|
+
brokerHash: `0x${string}`;
|
|
2142
|
+
usdcAddress: Address;
|
|
2143
|
+
relayAddress: Address;
|
|
2144
|
+
calls: DecodedCall[];
|
|
2145
|
+
callsFallback?: DecodedCall[];
|
|
2146
|
+
}
|
|
2147
|
+
declare class PerpDepositHandler {
|
|
2148
|
+
private readonly cfg;
|
|
2149
|
+
constructor(config: PerpDepositHandlerConfig);
|
|
2150
|
+
handle(request: PerpDepositRequest): Promise<PerpDepositResponse>;
|
|
2151
|
+
}
|
|
2152
|
+
|
|
2153
|
+
/**
|
|
2154
|
+
* Config for `createSubgraphPoolsProvider`.
|
|
2155
|
+
*/
|
|
2156
|
+
interface SubgraphPoolsProviderConfig {
|
|
1892
2157
|
/**
|
|
1893
|
-
*
|
|
1894
|
-
*
|
|
2158
|
+
* Fully qualified subgraph GraphQL endpoint.
|
|
2159
|
+
* Defaults to the PAFI-hosted subgraph (`PAFI_SUBGRAPH_URL`).
|
|
2160
|
+
* Override only when pointing at a staging or custom deployment.
|
|
1895
2161
|
*/
|
|
1896
|
-
|
|
2162
|
+
subgraphUrl?: string;
|
|
1897
2163
|
/**
|
|
1898
|
-
* Pool discovery
|
|
1899
|
-
*
|
|
2164
|
+
* Cache TTL in milliseconds. Pool discovery is near-static — a 30s
|
|
2165
|
+
* cache removes subgraph load without meaningfully delaying UX.
|
|
2166
|
+
* Set to 0 to disable caching. Default: 30_000.
|
|
1900
2167
|
*/
|
|
1901
|
-
|
|
2168
|
+
cacheTtlMs?: number;
|
|
1902
2169
|
/**
|
|
1903
|
-
*
|
|
1904
|
-
* `policy` + `relayService` instances already wired by the factory.
|
|
1905
|
-
* Omit to disable the `/claim` endpoint.
|
|
2170
|
+
* Optional fetch override for test harnesses. Defaults to global `fetch`.
|
|
1906
2171
|
*/
|
|
1907
|
-
|
|
1908
|
-
issuerSignerWallet: WalletClient;
|
|
1909
|
-
/** Defaults to the PAFI-deployed BatchExecutor for the target chain. */
|
|
1910
|
-
batchExecutorAddress?: Address;
|
|
1911
|
-
lockDurationMs?: number;
|
|
1912
|
-
};
|
|
1913
|
-
indexer?: {
|
|
1914
|
-
fromBlock?: bigint;
|
|
1915
|
-
cursorStore?: IIndexerCursorStore;
|
|
1916
|
-
confirmations?: number;
|
|
1917
|
-
batchSize?: number;
|
|
1918
|
-
pollIntervalMs?: number;
|
|
1919
|
-
/**
|
|
1920
|
-
* If `true`, the factory calls `indexer.start()` before returning.
|
|
1921
|
-
* Default: `false` — the caller decides when to begin polling.
|
|
1922
|
-
*/
|
|
1923
|
-
autoStart?: boolean;
|
|
1924
|
-
};
|
|
1925
|
-
}
|
|
1926
|
-
interface IssuerService {
|
|
1927
|
-
/** AuthService — login, logout, nonce management. */
|
|
1928
|
-
auth: AuthService;
|
|
1929
|
-
/** Session store — nonce + JWT session persistence. */
|
|
1930
|
-
session: ISessionStore;
|
|
1931
|
-
ledger: IPointLedger;
|
|
1932
|
-
policy: IPolicyEngine;
|
|
1933
|
-
/** RelayService — prepareMint / prepareBurn UserOp builders. */
|
|
1934
|
-
relay: RelayService;
|
|
1935
|
-
/** FeeManager — gas fee estimation. Undefined if not configured. */
|
|
1936
|
-
fee: FeeManager | undefined;
|
|
1937
|
-
/** All indexers keyed by PointToken address. */
|
|
1938
|
-
indexers: Map<Address, PointIndexer>;
|
|
2172
|
+
fetchImpl?: typeof fetch;
|
|
1939
2173
|
/**
|
|
1940
|
-
*
|
|
1941
|
-
* @deprecated use `indexers.get(tokenAddress)` for multi-token.
|
|
2174
|
+
* Optional clock override for tests.
|
|
1942
2175
|
*/
|
|
1943
|
-
|
|
1944
|
-
/** Framework-agnostic HTTP handlers — wire into Express / Fastify / Hono. */
|
|
1945
|
-
api: IssuerApiHandlers;
|
|
2176
|
+
now?: () => number;
|
|
1946
2177
|
}
|
|
1947
2178
|
/**
|
|
1948
|
-
*
|
|
2179
|
+
* Create a `PoolsProvider` backed by the PAFI subgraph.
|
|
1949
2180
|
*
|
|
1950
|
-
*
|
|
1951
|
-
*
|
|
1952
|
-
*
|
|
1953
|
-
* - `feeManager` → undefined (handleGasFee throws until configured)
|
|
1954
|
-
* - `poolsProvider` → undefined (handlePools throws until configured)
|
|
1955
|
-
* - `indexer.autoStart` → false
|
|
2181
|
+
* Queries the `pafiTokens` entity for the given `pointTokenAddress`,
|
|
2182
|
+
* reads its linked `Pool`, and returns a single-element `PoolKey[]`.
|
|
2183
|
+
* Multiple pools per token would require a subgraph schema change.
|
|
1956
2184
|
*
|
|
1957
|
-
*
|
|
2185
|
+
* The result is cached in-process with a short TTL (default 30s). Pool
|
|
2186
|
+
* discovery is near-static so this avoids hammering the subgraph without
|
|
2187
|
+
* blocking config changes for long.
|
|
2188
|
+
*
|
|
2189
|
+
* Returns `{ pools: [] }` if:
|
|
2190
|
+
* - the token is not registered on PAFI yet (no PafiToken entity)
|
|
2191
|
+
* - the token is registered but its pool has not been initialised
|
|
2192
|
+
* - the subgraph is unreachable or returns an error (logs to console,
|
|
2193
|
+
* does not throw — callers should handle empty pool list gracefully)
|
|
2194
|
+
*
|
|
2195
|
+
* Assumes the PAFI subgraph schema. Issuers with a custom subgraph must
|
|
2196
|
+
* implement `PoolsProvider` themselves instead of using this helper.
|
|
2197
|
+
*
|
|
2198
|
+
* @example
|
|
2199
|
+
* ```ts
|
|
2200
|
+
* import { createSubgraphPoolsProvider, createIssuerService } from "@pafi/issuer";
|
|
2201
|
+
*
|
|
2202
|
+
* const service = createIssuerService({
|
|
2203
|
+
* // ...other config
|
|
2204
|
+
* poolsProvider: createSubgraphPoolsProvider({
|
|
2205
|
+
* subgraphUrl: "https://graph.pacificfinance.org/subgraphs/name/pafi",
|
|
2206
|
+
* }),
|
|
2207
|
+
* });
|
|
2208
|
+
* ```
|
|
1958
2209
|
*/
|
|
1959
|
-
declare function
|
|
2210
|
+
declare function createSubgraphPoolsProvider(config?: SubgraphPoolsProviderConfig): PoolsProvider;
|
|
1960
2211
|
|
|
1961
2212
|
/**
|
|
1962
|
-
*
|
|
1963
|
-
*
|
|
1964
|
-
* All bigint fields are stored as decimal strings so the entry can be
|
|
1965
|
-
* JSON-serialized without precision loss. Convert back to bigint before
|
|
1966
|
-
* calling `computeUserOpHash` or `serializeUserOpToJsonRpc`.
|
|
2213
|
+
* Config for `createSubgraphNativeUsdtQuoter`.
|
|
1967
2214
|
*/
|
|
1968
|
-
interface
|
|
1969
|
-
sender: Address;
|
|
1970
|
-
nonce: string;
|
|
1971
|
-
callData: Hex;
|
|
1972
|
-
callGasLimit: string;
|
|
1973
|
-
verificationGasLimit: string;
|
|
1974
|
-
preVerificationGas: string;
|
|
1975
|
-
maxFeePerGas: string;
|
|
1976
|
-
maxPriorityFeePerGas: string;
|
|
1977
|
-
paymaster?: Address;
|
|
1978
|
-
paymasterVerificationGasLimit?: string;
|
|
1979
|
-
paymasterPostOpGasLimit?: string;
|
|
1980
|
-
paymasterData?: Hex;
|
|
1981
|
-
chainId: number;
|
|
1982
|
-
/** Hex-encoded userOpHash — the value the user signed via personal_sign. */
|
|
1983
|
-
userOpHash: Hex;
|
|
2215
|
+
interface SubgraphNativeUsdtQuoterConfig {
|
|
1984
2216
|
/**
|
|
1985
|
-
*
|
|
1986
|
-
*
|
|
1987
|
-
*
|
|
1988
|
-
* still want to submit without paymaster (paying ETH gas), and in
|
|
1989
|
-
* that case shouldn't be charged the PT fee. `/claim/submit` reads
|
|
1990
|
-
* this branch when its request body specifies
|
|
1991
|
-
* `variant: "fallback"`.
|
|
1992
|
-
*
|
|
1993
|
-
* Has a different `callData` (no PT.transfer prepended) and
|
|
1994
|
-
* therefore a different `userOpHash`. Paymaster fields are NOT
|
|
1995
|
-
* present — the fallback is by definition unsponsored.
|
|
2217
|
+
* Fully qualified subgraph GraphQL endpoint.
|
|
2218
|
+
* Defaults to the PAFI-hosted subgraph (`PAFI_SUBGRAPH_URL`).
|
|
2219
|
+
* Override only when pointing at a staging or custom deployment.
|
|
1996
2220
|
*/
|
|
1997
|
-
|
|
1998
|
-
|
|
1999
|
-
|
|
2000
|
-
|
|
2001
|
-
|
|
2002
|
-
|
|
2003
|
-
|
|
2221
|
+
subgraphUrl?: string;
|
|
2222
|
+
/**
|
|
2223
|
+
* Decimals of the USDT token. Defaults to 6 (standard USDT/USDC on
|
|
2224
|
+
* Base, Ethereum, Polygon). Override for chains where USDT uses a
|
|
2225
|
+
* different decimals value.
|
|
2226
|
+
*/
|
|
2227
|
+
usdtDecimals?: number;
|
|
2228
|
+
/**
|
|
2229
|
+
* Decimals of the native token (ETH on Base/mainnet/Arbitrum/Optimism,
|
|
2230
|
+
* MATIC on Polygon). Default: 18.
|
|
2231
|
+
*/
|
|
2232
|
+
nativeDecimals?: number;
|
|
2233
|
+
/**
|
|
2234
|
+
* Cache TTL in milliseconds. ETH price drifts slowly relative to gas
|
|
2235
|
+
* estimation needs — a 30s cache keeps fees stable across bursts of
|
|
2236
|
+
* requests without letting them go stale during volatile markets.
|
|
2237
|
+
* Set to 0 to disable caching. Default: 30_000.
|
|
2238
|
+
*/
|
|
2239
|
+
cacheTtlMs?: number;
|
|
2240
|
+
/**
|
|
2241
|
+
* Fallback price (USDT per native token, human-readable float) used
|
|
2242
|
+
* when the subgraph is unreachable. This keeps the backend operational
|
|
2243
|
+
* during subgraph outages rather than bricking cashouts. The fee will
|
|
2244
|
+
* be slightly off but the operator still gets paid. Default: 3000.
|
|
2245
|
+
*/
|
|
2246
|
+
fallbackEthPriceUsd?: number;
|
|
2247
|
+
/** Optional fetch override for test harnesses. */
|
|
2248
|
+
fetchImpl?: typeof fetch;
|
|
2249
|
+
/** Optional clock override for tests. */
|
|
2250
|
+
now?: () => number;
|
|
2004
2251
|
}
|
|
2005
2252
|
/**
|
|
2006
|
-
*
|
|
2253
|
+
* Create a native→USDT quoter backed by the PAFI subgraph's
|
|
2254
|
+
* `Bundle.ethPriceUSD`. The returned function has the shape
|
|
2255
|
+
* `(amountNative: bigint) => Promise<bigint>` and can be passed as
|
|
2256
|
+
* `quoteNativeToFee` to `FeeManager` — in v1.4 the fee currency
|
|
2257
|
+
* is configured at the integration layer, not hardcoded here.
|
|
2007
2258
|
*
|
|
2008
|
-
*
|
|
2009
|
-
*
|
|
2010
|
-
*
|
|
2011
|
-
*
|
|
2259
|
+
* Used by `FeeManager.estimateGasFee()` to convert the gas cost into
|
|
2260
|
+
* an ERC-20 amount charged as part of the sponsored UserOp batch.
|
|
2261
|
+
* Price precision is not critical — a 1-2% drift is acceptable since
|
|
2262
|
+
* the fee manager applies a `gasPremiumBps` buffer.
|
|
2012
2263
|
*
|
|
2013
|
-
* The
|
|
2014
|
-
*
|
|
2264
|
+
* The result is cached in-process with a short TTL (default 30s). If
|
|
2265
|
+
* the subgraph is unreachable, falls back to `fallbackEthPriceUsd` so
|
|
2266
|
+
* gas estimation doesn't block user flow during a subgraph outage.
|
|
2267
|
+
*
|
|
2268
|
+
* @example
|
|
2269
|
+
* ```ts
|
|
2270
|
+
* import { createSubgraphNativeUsdtQuoter, createIssuerService } from "@pafi-dev/issuer";
|
|
2271
|
+
*
|
|
2272
|
+
* const service = createIssuerService({
|
|
2273
|
+
* // ...other config
|
|
2274
|
+
* fee: {
|
|
2275
|
+
* quoteNativeToFee: createSubgraphNativeUsdtQuoter({
|
|
2276
|
+
* subgraphUrl: "https://graph.pacificfinance.org/subgraphs/name/pafi",
|
|
2277
|
+
* }),
|
|
2278
|
+
* },
|
|
2279
|
+
* });
|
|
2280
|
+
* ```
|
|
2015
2281
|
*/
|
|
2016
|
-
|
|
2017
|
-
save(lockId: string, entry: PendingUserOpEntry, ttlSeconds: number): Promise<void>;
|
|
2018
|
-
get(lockId: string): Promise<PendingUserOpEntry | null>;
|
|
2019
|
-
delete(lockId: string): Promise<void>;
|
|
2020
|
-
}
|
|
2282
|
+
declare function createSubgraphNativeUsdtQuoter(config?: SubgraphNativeUsdtQuoterConfig): (amountNative: bigint) => Promise<bigint>;
|
|
2021
2283
|
|
|
2284
|
+
interface NativePtQuoterConfig {
|
|
2285
|
+
/** Viem PublicClient — used to call Chainlink on-chain. */
|
|
2286
|
+
provider: PublicClient;
|
|
2287
|
+
/** Address of the PointToken being traded. */
|
|
2288
|
+
pointTokenAddress: Address;
|
|
2289
|
+
/** Chainlink ETH/USD feed address. Defaults to Base mainnet feed. */
|
|
2290
|
+
chainlinkFeedAddress?: Address;
|
|
2291
|
+
/** PAFI subgraph GraphQL endpoint. */
|
|
2292
|
+
subgraphUrl?: string;
|
|
2293
|
+
/** Cache TTL in ms. Default: 30_000. */
|
|
2294
|
+
cacheTtlMs?: number;
|
|
2295
|
+
/** Fallback ETH price (USD) when Chainlink is unreachable. Default: 3000. */
|
|
2296
|
+
fallbackEthPriceUsd?: number;
|
|
2297
|
+
/** Fallback PT price (USDT per 1 PT) when subgraph is unreachable. Default: 0.1. */
|
|
2298
|
+
fallbackPtPriceUsdt?: number;
|
|
2299
|
+
fetchImpl?: typeof fetch;
|
|
2300
|
+
now?: () => number;
|
|
2301
|
+
}
|
|
2022
2302
|
/**
|
|
2023
|
-
*
|
|
2024
|
-
* signature into the JSON-RPC wire format for `eth_sendUserOperation`.
|
|
2303
|
+
* Create a native→PT quoter for use as `FeeManager.quoteNativeToFee`.
|
|
2025
2304
|
*
|
|
2026
|
-
*
|
|
2027
|
-
*
|
|
2305
|
+
* Converts ETH gas cost → USDT (via Chainlink ETH/USD) → PT (via subgraph
|
|
2306
|
+
* pool price), returning the fee amount in PT raw units (18 decimals).
|
|
2307
|
+
*
|
|
2308
|
+
* Formula:
|
|
2309
|
+
* feeInPT = amountNative × ethPrice_8dec × ptPerUsdt_18dec / 10^26
|
|
2310
|
+
*
|
|
2311
|
+
* Both prices are cached in-process (default 30s TTL).
|
|
2312
|
+
*
|
|
2313
|
+
* @example
|
|
2314
|
+
* ```ts
|
|
2315
|
+
* fee: {
|
|
2316
|
+
* quoteNativeToFee: createNativePtQuoter({
|
|
2317
|
+
* provider,
|
|
2318
|
+
* pointTokenAddress: "0x...",
|
|
2319
|
+
* chainlinkFeedAddress: getContractAddresses(chainId).chainlinkEthUsd,
|
|
2320
|
+
* }),
|
|
2321
|
+
* }
|
|
2322
|
+
* ```
|
|
2028
2323
|
*/
|
|
2029
|
-
declare function
|
|
2324
|
+
declare function createNativePtQuoter(config: NativePtQuoterConfig): (amountNative: bigint) => Promise<bigint>;
|
|
2030
2325
|
|
|
2031
2326
|
/**
|
|
2032
|
-
*
|
|
2033
|
-
*
|
|
2034
|
-
* `
|
|
2035
|
-
*
|
|
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`.
|
|
2327
|
+
* Combined off-chain + on-chain balance for a single user / token pair.
|
|
2328
|
+
*
|
|
2329
|
+
* - `offChain` — the issuer's ledger balance (available, excluding locks)
|
|
2330
|
+
* - `onChain` — the user's ERC-20 balance from `PointToken.balanceOf`
|
|
2331
|
+
* - `total` — `offChain + onChain` (what the Issuer App displays)
|
|
2056
2332
|
*/
|
|
2057
|
-
|
|
2333
|
+
interface CombinedBalance {
|
|
2334
|
+
offChain: bigint;
|
|
2335
|
+
onChain: bigint;
|
|
2336
|
+
total: bigint;
|
|
2337
|
+
}
|
|
2338
|
+
interface BalanceAggregatorConfig {
|
|
2339
|
+
provider: PublicClient;
|
|
2340
|
+
ledger: IPointLedger;
|
|
2341
|
+
}
|
|
2058
2342
|
/**
|
|
2059
|
-
*
|
|
2060
|
-
*
|
|
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
|
|
2343
|
+
* v1.4 utility — aggregates off-chain + on-chain point balances into a
|
|
2344
|
+
* single view for the "combined balance" UI in the Issuer App.
|
|
2070
2345
|
*
|
|
2071
|
-
*
|
|
2072
|
-
*
|
|
2073
|
-
*
|
|
2074
|
-
* hash) fail at validation.
|
|
2346
|
+
* The `/user` API handler uses this internally; the helper is exposed
|
|
2347
|
+
* publicly so Issuer Apps can call it directly without going through
|
|
2348
|
+
* the HTTP layer (e.g., for server-rendered pages or admin dashboards).
|
|
2075
2349
|
*
|
|
2076
|
-
*
|
|
2077
|
-
* (
|
|
2078
|
-
* estimates.
|
|
2350
|
+
* See [REQUIREMENTS_V2.md] §1 — "The Issuer App displays a combined
|
|
2351
|
+
* balance (off-chain points + on-chain PT) and does not surface USDT."
|
|
2079
2352
|
*/
|
|
2080
|
-
declare
|
|
2081
|
-
|
|
2082
|
-
|
|
2083
|
-
|
|
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;
|
|
2353
|
+
declare class BalanceAggregator {
|
|
2354
|
+
private readonly provider;
|
|
2355
|
+
private readonly ledger;
|
|
2356
|
+
constructor(config: BalanceAggregatorConfig);
|
|
2109
2357
|
/**
|
|
2110
|
-
*
|
|
2111
|
-
*
|
|
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.
|
|
2358
|
+
* Combined balance for a single (user, token) pair. Fetches off-chain
|
|
2359
|
+
* + on-chain in parallel.
|
|
2115
2360
|
*/
|
|
2116
|
-
|
|
2117
|
-
maxFeePerGas: bigint;
|
|
2118
|
-
maxPriorityFeePerGas: bigint;
|
|
2119
|
-
};
|
|
2361
|
+
getCombinedBalance(user: Address, pointToken: Address): Promise<CombinedBalance>;
|
|
2120
2362
|
/**
|
|
2121
|
-
*
|
|
2122
|
-
*
|
|
2123
|
-
*
|
|
2363
|
+
* Combined balance for multiple tokens owned by the same user. Runs
|
|
2364
|
+
* all lookups in parallel. Returns a Map keyed by the token address
|
|
2365
|
+
* (same casing as supplied — caller should normalize if needed).
|
|
2124
2366
|
*/
|
|
2125
|
-
|
|
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;
|
|
2367
|
+
getCombinedBalanceMulti(user: Address, pointTokens: Address[]): Promise<Map<Address, CombinedBalance>>;
|
|
2146
2368
|
}
|
|
2147
|
-
|
|
2148
|
-
|
|
2369
|
+
|
|
2370
|
+
/**
|
|
2371
|
+
* Typed errors thrown by the helpers below — issuer controllers map
|
|
2372
|
+
* these to the appropriate HTTP status. We don't depend on @nestjs/common
|
|
2373
|
+
* here because the SDK is framework-agnostic; the consuming controller
|
|
2374
|
+
* wraps each one in its preferred exception class.
|
|
2375
|
+
*/
|
|
2376
|
+
declare class BundlerNotConfiguredError extends Error {
|
|
2377
|
+
readonly code = "BUNDLER_NOT_CONFIGURED";
|
|
2378
|
+
constructor();
|
|
2379
|
+
}
|
|
2380
|
+
declare class BundlerRejectedError extends Error {
|
|
2381
|
+
readonly code = "BUNDLER_REJECTED";
|
|
2382
|
+
readonly cause: unknown;
|
|
2383
|
+
constructor(message: string, cause: unknown);
|
|
2384
|
+
}
|
|
2385
|
+
interface RequestPaymasterParams {
|
|
2386
|
+
/** PAFI backend client. When `null` / `undefined` → returns `undefined`. */
|
|
2387
|
+
client: PafiBackendClient | null | undefined;
|
|
2388
|
+
chainId: number;
|
|
2389
|
+
scenario: string;
|
|
2390
|
+
/** UserOp skeleton — must have all gas + fee fields set. */
|
|
2391
|
+
userOp: {
|
|
2392
|
+
sender: Address;
|
|
2393
|
+
nonce: bigint;
|
|
2394
|
+
callData: Hex;
|
|
2395
|
+
callGasLimit: bigint;
|
|
2396
|
+
verificationGasLimit: bigint;
|
|
2397
|
+
preVerificationGas: bigint;
|
|
2398
|
+
maxFeePerGas: bigint;
|
|
2399
|
+
maxPriorityFeePerGas: bigint;
|
|
2400
|
+
};
|
|
2401
|
+
/** Target contract (typically the PointToken). */
|
|
2402
|
+
pointTokenAddress: Address;
|
|
2149
2403
|
/**
|
|
2150
|
-
*
|
|
2151
|
-
*
|
|
2152
|
-
*
|
|
2153
|
-
* the `variant` flag to dispatch.
|
|
2404
|
+
* Function name to surface in audit / paymaster context. Defaults to
|
|
2405
|
+
* a per-scenario sensible value (`mint` / `burn` / `swap` / generic
|
|
2406
|
+
* scenario name).
|
|
2154
2407
|
*/
|
|
2155
|
-
|
|
2156
|
-
/**
|
|
2157
|
-
|
|
2408
|
+
functionName?: string;
|
|
2409
|
+
/** Optional logger for the "sponsorship declined" warning. */
|
|
2410
|
+
onWarning?: (msg: string) => void;
|
|
2158
2411
|
}
|
|
2159
2412
|
/**
|
|
2160
|
-
*
|
|
2161
|
-
*
|
|
2413
|
+
* Thin wrapper around `PafiBackendClient.requestSponsorship` with the
|
|
2414
|
+
* "non-fatal on failure" semantics every issuer wants:
|
|
2162
2415
|
*
|
|
2163
|
-
*
|
|
2164
|
-
*
|
|
2165
|
-
*
|
|
2166
|
-
*
|
|
2167
|
-
*
|
|
2168
|
-
*
|
|
2169
|
-
*
|
|
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.
|
|
2416
|
+
* - When the client is missing → returns `undefined` (the caller falls
|
|
2417
|
+
* back to a self-funded UserOp).
|
|
2418
|
+
* - When the network call throws OR PAFI declines (rate limit, intent
|
|
2419
|
+
* rejection, paymaster outage) → returns `undefined` after logging,
|
|
2420
|
+
* so the controller doesn't hard-fail. The caller's
|
|
2421
|
+
* `prepareMobileUserOp` / `mergePaymasterFields` will gracefully
|
|
2422
|
+
* produce the unsponsored variant.
|
|
2174
2423
|
*
|
|
2175
|
-
* Replaces ~
|
|
2424
|
+
* Replaces ~30 LoC of try/catch + scenario-to-function mapping every
|
|
2425
|
+
* issuer would copy.
|
|
2176
2426
|
*/
|
|
2177
|
-
declare function
|
|
2178
|
-
|
|
2179
|
-
|
|
2180
|
-
|
|
2181
|
-
|
|
2182
|
-
|
|
2183
|
-
|
|
2184
|
-
|
|
2185
|
-
|
|
2186
|
-
|
|
2187
|
-
|
|
2188
|
-
|
|
2189
|
-
|
|
2190
|
-
|
|
2191
|
-
|
|
2192
|
-
issuer: IssuerRegistryRecord;
|
|
2193
|
-
/** Current on-chain PointToken.totalSupply(). */
|
|
2194
|
-
totalSupply: bigint;
|
|
2195
|
-
/** declaredTotalSupply × capBasisPoints / 10000. */
|
|
2196
|
-
hardCap: bigint;
|
|
2197
|
-
/** hardCap − totalSupply (clamped to 0). */
|
|
2198
|
-
remaining: bigint;
|
|
2427
|
+
declare function requestPaymaster(params: RequestPaymasterParams): Promise<Awaited<ReturnType<PafiBackendClient["requestSponsorship"]>> | undefined>;
|
|
2428
|
+
interface RelayUserOpParams {
|
|
2429
|
+
client: PafiBackendClient | null | undefined;
|
|
2430
|
+
/** EntryPoint address — typically `ENTRY_POINT_V08` from core. */
|
|
2431
|
+
entryPoint: typeof ENTRY_POINT_V08 | string;
|
|
2432
|
+
userOp: Record<string, string | null>;
|
|
2433
|
+
/** EIP-7702 authorization (delegation UserOps only). */
|
|
2434
|
+
eip7702Auth?: {
|
|
2435
|
+
chainId: string;
|
|
2436
|
+
address: string;
|
|
2437
|
+
nonce: string;
|
|
2438
|
+
r: string;
|
|
2439
|
+
s: string;
|
|
2440
|
+
yParity: string;
|
|
2441
|
+
};
|
|
2199
2442
|
}
|
|
2200
2443
|
/**
|
|
2201
|
-
*
|
|
2202
|
-
*
|
|
2444
|
+
* Submit a serialized UserOp to the Pimlico bundler via PAFI's
|
|
2445
|
+
* sponsor-relayer. Handles the "client missing" / "bundler rejected"
|
|
2446
|
+
* branches as typed errors so the controller can map to HTTP cleanly.
|
|
2447
|
+
*
|
|
2448
|
+
* Every issuer mobile flow has this exact wrapper — moved into SDK
|
|
2449
|
+
* to drop ~30 LoC of try/catch + error-shape boilerplate per
|
|
2450
|
+
* controller.
|
|
2451
|
+
*
|
|
2452
|
+
* Throws:
|
|
2453
|
+
* - `BundlerNotConfiguredError` — caller didn't configure
|
|
2454
|
+
* `PafiBackendClient`. Map to 503.
|
|
2455
|
+
* - `BundlerRejectedError` — bundler returned an error. Map to 422
|
|
2456
|
+
* (the FE can show the reason — usually `AA21` / `AA34` / etc.).
|
|
2203
2457
|
*/
|
|
2204
|
-
declare
|
|
2205
|
-
|
|
2206
|
-
|
|
2207
|
-
constructor(code: "ISSUER_NOT_REGISTERED" | "ISSUER_INACTIVE" | "MINT_CAP_EXCEEDED", message: string, details?: Record<string, unknown> | undefined);
|
|
2208
|
-
}
|
|
2458
|
+
declare function relayUserOp(params: RelayUserOpParams): Promise<{
|
|
2459
|
+
userOpHash: Hex;
|
|
2460
|
+
}>;
|
|
2209
2461
|
|
|
2210
2462
|
/**
|
|
2211
|
-
*
|
|
2212
|
-
*
|
|
2213
|
-
* Reads IssuerRegistry + PointToken on-chain state and pre-validates
|
|
2214
|
-
* mint requests before the user submits a UserOp. Catching these
|
|
2215
|
-
* off-chain lets issuers fail fast with a clear error rather than
|
|
2216
|
-
* wasting gas on a revert.
|
|
2463
|
+
* Top-level configuration for `createIssuerService`.
|
|
2217
2464
|
*
|
|
2218
|
-
*
|
|
2219
|
-
*
|
|
2220
|
-
*
|
|
2221
|
-
*
|
|
2222
|
-
* (thundering-herd protection)
|
|
2465
|
+
* In v1.4 the SDK is HTTP-client-free: it signs EIP-712 messages, reads
|
|
2466
|
+
* on-chain state, builds unsigned UserOperations, and maintains the
|
|
2467
|
+
* off-chain ledger. It never broadcasts transactions — that's the
|
|
2468
|
+
* frontend's responsibility via Bundler + Paymaster.
|
|
2223
2469
|
*
|
|
2224
|
-
*
|
|
2225
|
-
*
|
|
2470
|
+
* **Multi-token (0.2.0+):** Pass `pointTokenAddresses: Address[]` to
|
|
2471
|
+
* support multiple PointTokens under a single issuer backend. Legacy
|
|
2472
|
+
* `pointTokenAddress: Address` still works for single-token deployments.
|
|
2473
|
+
* When both are provided, `pointTokenAddresses` takes precedence.
|
|
2226
2474
|
*/
|
|
2227
|
-
|
|
2228
|
-
|
|
2229
|
-
|
|
2230
|
-
|
|
2231
|
-
|
|
2232
|
-
|
|
2233
|
-
constructor(provider: PublicClient, registryAddress: Address);
|
|
2475
|
+
interface IssuerServiceConfig {
|
|
2476
|
+
chainId: number;
|
|
2477
|
+
/** Legacy single-token shortcut; prefer `pointTokenAddresses`. */
|
|
2478
|
+
pointTokenAddress?: Address;
|
|
2479
|
+
/** All PointToken addresses this issuer supports. */
|
|
2480
|
+
pointTokenAddresses?: Address[];
|
|
2234
2481
|
/**
|
|
2235
|
-
*
|
|
2236
|
-
*
|
|
2482
|
+
* Issuer-specific contract addresses merged into the `/config` response.
|
|
2483
|
+
* PAFI-owned addresses (batchExecutor, usdt, issuerRegistry, mintingOracle,
|
|
2484
|
+
* pafiHook) are auto-resolved from `getContractAddresses(chainId)` and
|
|
2485
|
+
* can be omitted. Only `pointToken` / `pointTokens` must be provided.
|
|
2237
2486
|
*/
|
|
2238
|
-
|
|
2487
|
+
contracts?: Pick<ApiConfigResponse["contracts"], "pointToken" | "pointTokens" | "relay">;
|
|
2239
2488
|
/**
|
|
2240
|
-
*
|
|
2241
|
-
*
|
|
2489
|
+
* Shared `PublicClient` used for on-chain reads, simulation, indexer
|
|
2490
|
+
* polling, and gas-price lookups. Must be pointed at the target chain.
|
|
2242
2491
|
*/
|
|
2243
|
-
|
|
2492
|
+
provider: PublicClient;
|
|
2493
|
+
auth: {
|
|
2494
|
+
jwtSecret: string;
|
|
2495
|
+
/** SIWE-style login-message domain, e.g. `"app.example.com"`. */
|
|
2496
|
+
domain: string;
|
|
2497
|
+
/** Passed straight to `jose` (`"24h"`, `"7d"`, …). Default `"24h"`. */
|
|
2498
|
+
jwtExpiresIn?: string;
|
|
2499
|
+
};
|
|
2244
2500
|
/**
|
|
2245
|
-
*
|
|
2246
|
-
*
|
|
2501
|
+
* Off-chain point ledger — the source of truth for user balances and
|
|
2502
|
+
* in-flight minting locks. Every issuer provides their own database-backed
|
|
2503
|
+
* implementation (Postgres, Redis, etc.) that implements `IPointLedger`.
|
|
2504
|
+
* The SDK does not ship a production ledger; each issuer's data model and
|
|
2505
|
+
* infrastructure are different.
|
|
2247
2506
|
*/
|
|
2248
|
-
|
|
2507
|
+
ledger: IPointLedger;
|
|
2249
2508
|
/**
|
|
2250
|
-
*
|
|
2251
|
-
*
|
|
2509
|
+
* Policy engine — optional, defaults to `DefaultPolicyEngine` which checks
|
|
2510
|
+
* off-chain balance. Extend or replace to add KYC, volume caps, etc.
|
|
2252
2511
|
*/
|
|
2253
|
-
|
|
2512
|
+
policy?: IPolicyEngine;
|
|
2513
|
+
/** Session store — optional, defaults to `MemorySessionStore` (dev/test only). */
|
|
2514
|
+
sessionStore?: ISessionStore;
|
|
2254
2515
|
/**
|
|
2255
|
-
*
|
|
2256
|
-
*
|
|
2257
|
-
* Throws `IssuerStateError` with:
|
|
2258
|
-
* - `ISSUER_NOT_REGISTERED` — registry has no record for this issuer
|
|
2259
|
-
* - `ISSUER_INACTIVE` — issuer.active is false
|
|
2260
|
-
* - `MINT_CAP_EXCEEDED` — totalSupply + amount would exceed hardCap
|
|
2261
|
-
*
|
|
2262
|
-
* Returns the fetched state on success so callers can log without a
|
|
2263
|
-
* second RPC round-trip.
|
|
2516
|
+
* Fee management config. If omitted the `handleGasFee` endpoint will
|
|
2517
|
+
* throw "not configured" at request time.
|
|
2264
2518
|
*/
|
|
2265
|
-
|
|
2266
|
-
|
|
2519
|
+
fee?: Omit<FeeManagerConfig, "provider">;
|
|
2520
|
+
/**
|
|
2521
|
+
* Pool discovery function for `handlePools`. If omitted the endpoint
|
|
2522
|
+
* throws "not configured" at request time.
|
|
2523
|
+
*/
|
|
2524
|
+
poolsProvider?: PoolsProvider;
|
|
2525
|
+
/**
|
|
2526
|
+
* Enables `handleClaim`. The factory combines these with the shared
|
|
2527
|
+
* `policy` + `relayService` instances already wired by the factory.
|
|
2528
|
+
* Omit to disable the `/claim` endpoint.
|
|
2529
|
+
*/
|
|
2530
|
+
claim?: {
|
|
2531
|
+
issuerSignerWallet: WalletClient;
|
|
2532
|
+
/** Defaults to the PAFI-deployed BatchExecutor for the target chain. */
|
|
2533
|
+
batchExecutorAddress?: Address;
|
|
2534
|
+
lockDurationMs?: number;
|
|
2535
|
+
};
|
|
2536
|
+
indexer?: {
|
|
2537
|
+
fromBlock?: bigint;
|
|
2538
|
+
cursorStore?: IIndexerCursorStore;
|
|
2539
|
+
confirmations?: number;
|
|
2540
|
+
batchSize?: number;
|
|
2541
|
+
pollIntervalMs?: number;
|
|
2542
|
+
/**
|
|
2543
|
+
* If `true`, the factory calls `indexer.start()` before returning.
|
|
2544
|
+
* Default: `false` — the caller decides when to begin polling.
|
|
2545
|
+
*/
|
|
2546
|
+
autoStart?: boolean;
|
|
2547
|
+
};
|
|
2548
|
+
}
|
|
2549
|
+
interface IssuerService {
|
|
2550
|
+
/** AuthService — login, logout, nonce management. */
|
|
2551
|
+
auth: AuthService;
|
|
2552
|
+
/** Session store — nonce + JWT session persistence. */
|
|
2553
|
+
session: ISessionStore;
|
|
2554
|
+
ledger: IPointLedger;
|
|
2555
|
+
policy: IPolicyEngine;
|
|
2556
|
+
/** RelayService — prepareMint / prepareBurn UserOp builders. */
|
|
2557
|
+
relay: RelayService;
|
|
2558
|
+
/** FeeManager — gas fee estimation. Undefined if not configured. */
|
|
2559
|
+
fee: FeeManager | undefined;
|
|
2560
|
+
/** All indexers keyed by PointToken address. */
|
|
2561
|
+
indexers: Map<Address, PointIndexer>;
|
|
2562
|
+
/**
|
|
2563
|
+
* First indexer. Kept for backward compat with 0.1.x callers.
|
|
2564
|
+
* @deprecated use `indexers.get(tokenAddress)` for multi-token.
|
|
2565
|
+
*/
|
|
2566
|
+
indexer: PointIndexer;
|
|
2567
|
+
/** Framework-agnostic HTTP handlers — wire into Express / Fastify / Hono. */
|
|
2568
|
+
api: IssuerApiHandlers;
|
|
2267
2569
|
}
|
|
2570
|
+
/**
|
|
2571
|
+
* Wire a fully-functional issuer service from a single config object.
|
|
2572
|
+
*
|
|
2573
|
+
* Defaults:
|
|
2574
|
+
* - `sessionStore` → `MemorySessionStore` (dev/test only — replace in prod)
|
|
2575
|
+
* - `policy` → `DefaultPolicyEngine({ ledger })`
|
|
2576
|
+
* - `feeManager` → undefined (handleGasFee throws until configured)
|
|
2577
|
+
* - `poolsProvider` → undefined (handlePools throws until configured)
|
|
2578
|
+
* - `indexer.autoStart` → false
|
|
2579
|
+
*
|
|
2580
|
+
* Throws synchronously if any required field is missing.
|
|
2581
|
+
*/
|
|
2582
|
+
declare function createIssuerService(config: IssuerServiceConfig): IssuerService;
|
|
2268
2583
|
|
|
2269
2584
|
/** SDK package version — bumped on every release */
|
|
2270
2585
|
declare const PAFI_ISSUER_SDK_VERSION = "0.4.0";
|
|
2271
2586
|
|
|
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 };
|
|
2587
|
+
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 HandleMobilePrepareParams, type HandleMobilePrepareResult, type HandleMobileSubmitParams, 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, PTClaimError, PTClaimHandler, type PTClaimHandlerConfig, type PTClaimRequest, type PTClaimResponse, PTRedeemError, PTRedeemHandler, type PTRedeemHandlerConfig, type PTRedeemRequest, type PTRedeemResponse, PafiBackendClient, type PafiBackendConfig, PafiBackendError, type PafiBackendErrorCode, type PendingCredit, type PendingUserOpEntry, PendingUserOpNotFoundError, PerpDepositError, PerpDepositHandler, type PerpDepositHandlerConfig, type PerpDepositRequest, type PerpDepositResponse, 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, SwapError, SwapHandler, type SwapHandlerConfig, type SwapRequest, type SwapResponse, TopUpRedemptionError, TopUpRedemptionHandler, type TopUpRedemptionHandlerConfig, type TopUpRedemptionRequest, type TopUpRedemptionResponse, authenticateRequest, createIssuerService, createNativePtQuoter, createSubgraphNativeUsdtQuoter, createSubgraphPoolsProvider, handleClaimStatus, handleMobilePrepare, handleMobileSubmit, handleRedeemStatus, mergePaymasterFields, prepareMobileUserOp, relayUserOp, requestPaymaster, serializeEntryToJsonRpc, serializeUserOpTypedData };
|