@pafi-dev/issuer 0.5.33 → 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 +706 -174
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +923 -516
- package/dist/index.d.ts +923 -516
- package/dist/index.js +702 -162
- 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, UserOpTypedData } from '@pafi-dev/core';
|
|
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,444 +1528,105 @@ 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)
|
|
1571
|
-
*
|
|
1572
|
-
* Assumes the PAFI subgraph schema. Issuers with a custom subgraph must
|
|
1573
|
-
* implement `PoolsProvider` themselves instead of using this helper.
|
|
1575
|
+
* Storage backend for pending UserOps in the mobile prepare/submit pattern.
|
|
1574
1576
|
*
|
|
1575
|
-
*
|
|
1576
|
-
*
|
|
1577
|
-
*
|
|
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
|
|
1578
1581
|
*
|
|
1579
|
-
*
|
|
1580
|
-
*
|
|
1581
|
-
* poolsProvider: createSubgraphPoolsProvider({
|
|
1582
|
-
* subgraphUrl: "https://graph.pacificfinance.org/subgraphs/name/pafi",
|
|
1583
|
-
* }),
|
|
1584
|
-
* });
|
|
1585
|
-
* ```
|
|
1586
|
-
*/
|
|
1587
|
-
declare function createSubgraphPoolsProvider(config?: SubgraphPoolsProviderConfig): PoolsProvider;
|
|
1588
|
-
|
|
1589
|
-
/**
|
|
1590
|
-
* Config for `createSubgraphNativeUsdtQuoter`.
|
|
1582
|
+
* The default implementation in the gg56 boilerplate uses Redis with
|
|
1583
|
+
* a short TTL matching the MintRequest / BurnRequest deadline.
|
|
1591
1584
|
*/
|
|
1592
|
-
interface
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
* Override only when pointing at a staging or custom deployment.
|
|
1597
|
-
*/
|
|
1598
|
-
subgraphUrl?: string;
|
|
1599
|
-
/**
|
|
1600
|
-
* Decimals of the USDT token. Defaults to 6 (standard USDT/USDC on
|
|
1601
|
-
* Base, Ethereum, Polygon). Override for chains where USDT uses a
|
|
1602
|
-
* different decimals value.
|
|
1603
|
-
*/
|
|
1604
|
-
usdtDecimals?: number;
|
|
1605
|
-
/**
|
|
1606
|
-
* Decimals of the native token (ETH on Base/mainnet/Arbitrum/Optimism,
|
|
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;
|
|
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>;
|
|
1628
1589
|
}
|
|
1590
|
+
|
|
1629
1591
|
/**
|
|
1630
|
-
*
|
|
1631
|
-
*
|
|
1632
|
-
* `(amountNative: bigint) => Promise<bigint>` and can be passed as
|
|
1633
|
-
* `quoteNativeToFee` to `FeeManager` — in v1.4 the fee currency
|
|
1634
|
-
* is configured at the integration layer, not hardcoded here.
|
|
1635
|
-
*
|
|
1636
|
-
* Used by `FeeManager.estimateGasFee()` to convert the gas cost into
|
|
1637
|
-
* an ERC-20 amount charged as part of the sponsored UserOp batch.
|
|
1638
|
-
* Price precision is not critical — a 1-2% drift is acceptable since
|
|
1639
|
-
* the fee manager applies a `gasPremiumBps` buffer.
|
|
1640
|
-
*
|
|
1641
|
-
* The result is cached in-process with a short TTL (default 30s). If
|
|
1642
|
-
* the subgraph is unreachable, falls back to `fallbackEthPriceUsd` so
|
|
1643
|
-
* gas estimation doesn't block user flow during a subgraph outage.
|
|
1644
|
-
*
|
|
1645
|
-
* @example
|
|
1646
|
-
* ```ts
|
|
1647
|
-
* import { createSubgraphNativeUsdtQuoter, createIssuerService } from "@pafi-dev/issuer";
|
|
1592
|
+
* Convert a stored `PendingUserOpEntry` (decimal-string fields) plus a
|
|
1593
|
+
* signature into the JSON-RPC wire format for `eth_sendUserOperation`.
|
|
1648
1594
|
*
|
|
1649
|
-
*
|
|
1650
|
-
*
|
|
1651
|
-
* fee: {
|
|
1652
|
-
* quoteNativeToFee: createSubgraphNativeUsdtQuoter({
|
|
1653
|
-
* subgraphUrl: "https://graph.pacificfinance.org/subgraphs/name/pafi",
|
|
1654
|
-
* }),
|
|
1655
|
-
* },
|
|
1656
|
-
* });
|
|
1657
|
-
* ```
|
|
1595
|
+
* Bridges the gap between the serialized storage format (decimal strings,
|
|
1596
|
+
* safe for JSON/Redis) and `serializeUserOpToJsonRpc` which expects bigints.
|
|
1658
1597
|
*/
|
|
1659
|
-
declare function
|
|
1598
|
+
declare function serializeEntryToJsonRpc(entry: PendingUserOpEntry, signature: Hex, variant?: "sponsored" | "fallback"): Record<string, string | null>;
|
|
1660
1599
|
|
|
1661
|
-
interface NativePtQuoterConfig {
|
|
1662
|
-
/** Viem PublicClient — used to call Chainlink on-chain. */
|
|
1663
|
-
provider: PublicClient;
|
|
1664
|
-
/** Address of the PointToken being traded. */
|
|
1665
|
-
pointTokenAddress: Address;
|
|
1666
|
-
/** Chainlink ETH/USD feed address. Defaults to Base mainnet feed. */
|
|
1667
|
-
chainlinkFeedAddress?: Address;
|
|
1668
|
-
/** PAFI subgraph GraphQL endpoint. */
|
|
1669
|
-
subgraphUrl?: string;
|
|
1670
|
-
/** Cache TTL in ms. Default: 30_000. */
|
|
1671
|
-
cacheTtlMs?: number;
|
|
1672
|
-
/** Fallback ETH price (USD) when Chainlink is unreachable. Default: 3000. */
|
|
1673
|
-
fallbackEthPriceUsd?: number;
|
|
1674
|
-
/** Fallback PT price (USDT per 1 PT) when subgraph is unreachable. Default: 0.1. */
|
|
1675
|
-
fallbackPtPriceUsdt?: number;
|
|
1676
|
-
fetchImpl?: typeof fetch;
|
|
1677
|
-
now?: () => number;
|
|
1678
|
-
}
|
|
1679
1600
|
/**
|
|
1680
|
-
*
|
|
1681
|
-
*
|
|
1682
|
-
*
|
|
1683
|
-
*
|
|
1684
|
-
*
|
|
1685
|
-
* Formula:
|
|
1686
|
-
* feeInPT = amountNative × ethPrice_8dec × ptPerUsdt_18dec / 10^26
|
|
1687
|
-
*
|
|
1688
|
-
* Both prices are cached in-process (default 30s TTL).
|
|
1689
|
-
*
|
|
1690
|
-
* @example
|
|
1691
|
-
* ```ts
|
|
1692
|
-
* fee: {
|
|
1693
|
-
* quoteNativeToFee: createNativePtQuoter({
|
|
1694
|
-
* provider,
|
|
1695
|
-
* pointTokenAddress: "0x...",
|
|
1696
|
-
* chainlinkFeedAddress: getContractAddresses(chainId).chainlinkEthUsd,
|
|
1697
|
-
* }),
|
|
1698
|
-
* }
|
|
1699
|
-
* ```
|
|
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).
|
|
1700
1605
|
*/
|
|
1701
|
-
|
|
1702
|
-
|
|
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
|
+
};
|
|
1703
1621
|
/**
|
|
1704
|
-
*
|
|
1705
|
-
*
|
|
1706
|
-
*
|
|
1707
|
-
* - `onChain` — the user's ERC-20 balance from `PointToken.balanceOf`
|
|
1708
|
-
* - `total` — `offChain + onChain` (what the Issuer App displays)
|
|
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`.
|
|
1709
1625
|
*/
|
|
1710
|
-
|
|
1711
|
-
offChain: bigint;
|
|
1712
|
-
onChain: bigint;
|
|
1713
|
-
total: bigint;
|
|
1714
|
-
}
|
|
1715
|
-
interface BalanceAggregatorConfig {
|
|
1716
|
-
provider: PublicClient;
|
|
1717
|
-
ledger: IPointLedger;
|
|
1718
|
-
}
|
|
1626
|
+
declare function serializeUserOpTypedData(td: UserOpTypedData): SerializedUserOpTypedData;
|
|
1719
1627
|
/**
|
|
1720
|
-
*
|
|
1721
|
-
*
|
|
1722
|
-
*
|
|
1723
|
-
* The `/user` API handler uses this internally; the helper is exposed
|
|
1724
|
-
* publicly so Issuer Apps can call it directly without going through
|
|
1725
|
-
* the HTTP layer (e.g., for server-rendered pages or admin dashboards).
|
|
1726
|
-
*
|
|
1727
|
-
* See [REQUIREMENTS_V2.md] §1 — "The Issuer App displays a combined
|
|
1728
|
-
* balance (off-chain points + on-chain PT) and does not surface USDT."
|
|
1729
|
-
*/
|
|
1730
|
-
declare class BalanceAggregator {
|
|
1731
|
-
private readonly provider;
|
|
1732
|
-
private readonly ledger;
|
|
1733
|
-
constructor(config: BalanceAggregatorConfig);
|
|
1734
|
-
/**
|
|
1735
|
-
* Combined balance for a single (user, token) pair. Fetches off-chain
|
|
1736
|
-
* + on-chain in parallel.
|
|
1737
|
-
*/
|
|
1738
|
-
getCombinedBalance(user: Address, pointToken: Address): Promise<CombinedBalance>;
|
|
1739
|
-
/**
|
|
1740
|
-
* Combined balance for multiple tokens owned by the same user. Runs
|
|
1741
|
-
* all lookups in parallel. Returns a Map keyed by the token address
|
|
1742
|
-
* (same casing as supplied — caller should normalize if needed).
|
|
1743
|
-
*/
|
|
1744
|
-
getCombinedBalanceMulti(user: Address, pointTokens: Address[]): Promise<Map<Address, CombinedBalance>>;
|
|
1745
|
-
}
|
|
1746
|
-
|
|
1747
|
-
/**
|
|
1748
|
-
* Top-level configuration for `createIssuerService`.
|
|
1749
|
-
*
|
|
1750
|
-
* In v1.4 the SDK is HTTP-client-free: it signs EIP-712 messages, reads
|
|
1751
|
-
* on-chain state, builds unsigned UserOperations, and maintains the
|
|
1752
|
-
* off-chain ledger. It never broadcasts transactions — that's the
|
|
1753
|
-
* frontend's responsibility via Bundler + Paymaster.
|
|
1754
|
-
*
|
|
1755
|
-
* **Multi-token (0.2.0+):** Pass `pointTokenAddresses: Address[]` to
|
|
1756
|
-
* support multiple PointTokens under a single issuer backend. Legacy
|
|
1757
|
-
* `pointTokenAddress: Address` still works for single-token deployments.
|
|
1758
|
-
* When both are provided, `pointTokenAddresses` takes precedence.
|
|
1759
|
-
*/
|
|
1760
|
-
interface IssuerServiceConfig {
|
|
1761
|
-
chainId: number;
|
|
1762
|
-
/** Legacy single-token shortcut; prefer `pointTokenAddresses`. */
|
|
1763
|
-
pointTokenAddress?: Address;
|
|
1764
|
-
/** All PointToken addresses this issuer supports. */
|
|
1765
|
-
pointTokenAddresses?: Address[];
|
|
1766
|
-
/**
|
|
1767
|
-
* Issuer-specific contract addresses merged into the `/config` response.
|
|
1768
|
-
* PAFI-owned addresses (batchExecutor, usdt, issuerRegistry, mintingOracle,
|
|
1769
|
-
* pafiHook) are auto-resolved from `getContractAddresses(chainId)` and
|
|
1770
|
-
* can be omitted. Only `pointToken` / `pointTokens` must be provided.
|
|
1771
|
-
*/
|
|
1772
|
-
contracts?: Pick<ApiConfigResponse["contracts"], "pointToken" | "pointTokens" | "relay">;
|
|
1773
|
-
/**
|
|
1774
|
-
* Shared `PublicClient` used for on-chain reads, simulation, indexer
|
|
1775
|
-
* polling, and gas-price lookups. Must be pointed at the target chain.
|
|
1776
|
-
*/
|
|
1777
|
-
provider: PublicClient;
|
|
1778
|
-
auth: {
|
|
1779
|
-
jwtSecret: string;
|
|
1780
|
-
/** SIWE-style login-message domain, e.g. `"app.example.com"`. */
|
|
1781
|
-
domain: string;
|
|
1782
|
-
/** Passed straight to `jose` (`"24h"`, `"7d"`, …). Default `"24h"`. */
|
|
1783
|
-
jwtExpiresIn?: string;
|
|
1784
|
-
};
|
|
1785
|
-
/**
|
|
1786
|
-
* Off-chain point ledger — the source of truth for user balances and
|
|
1787
|
-
* in-flight minting locks. Every issuer provides their own database-backed
|
|
1788
|
-
* implementation (Postgres, Redis, etc.) that implements `IPointLedger`.
|
|
1789
|
-
* The SDK does not ship a production ledger; each issuer's data model and
|
|
1790
|
-
* infrastructure are different.
|
|
1791
|
-
*/
|
|
1792
|
-
ledger: IPointLedger;
|
|
1793
|
-
/**
|
|
1794
|
-
* Policy engine — optional, defaults to `DefaultPolicyEngine` which checks
|
|
1795
|
-
* off-chain balance. Extend or replace to add KYC, volume caps, etc.
|
|
1796
|
-
*/
|
|
1797
|
-
policy?: IPolicyEngine;
|
|
1798
|
-
/** Session store — optional, defaults to `MemorySessionStore` (dev/test only). */
|
|
1799
|
-
sessionStore?: ISessionStore;
|
|
1800
|
-
/**
|
|
1801
|
-
* Fee management config. If omitted the `handleGasFee` endpoint will
|
|
1802
|
-
* throw "not configured" at request time.
|
|
1803
|
-
*/
|
|
1804
|
-
fee?: Omit<FeeManagerConfig, "provider">;
|
|
1805
|
-
/**
|
|
1806
|
-
* Pool discovery function for `handlePools`. If omitted the endpoint
|
|
1807
|
-
* throws "not configured" at request time.
|
|
1808
|
-
*/
|
|
1809
|
-
poolsProvider?: PoolsProvider;
|
|
1810
|
-
/**
|
|
1811
|
-
* Enables `handleClaim`. The factory combines these with the shared
|
|
1812
|
-
* `policy` + `relayService` instances already wired by the factory.
|
|
1813
|
-
* Omit to disable the `/claim` endpoint.
|
|
1814
|
-
*/
|
|
1815
|
-
claim?: {
|
|
1816
|
-
issuerSignerWallet: WalletClient;
|
|
1817
|
-
/** Defaults to the PAFI-deployed BatchExecutor for the target chain. */
|
|
1818
|
-
batchExecutorAddress?: Address;
|
|
1819
|
-
lockDurationMs?: number;
|
|
1820
|
-
};
|
|
1821
|
-
indexer?: {
|
|
1822
|
-
fromBlock?: bigint;
|
|
1823
|
-
cursorStore?: IIndexerCursorStore;
|
|
1824
|
-
confirmations?: number;
|
|
1825
|
-
batchSize?: number;
|
|
1826
|
-
pollIntervalMs?: number;
|
|
1827
|
-
/**
|
|
1828
|
-
* If `true`, the factory calls `indexer.start()` before returning.
|
|
1829
|
-
* Default: `false` — the caller decides when to begin polling.
|
|
1830
|
-
*/
|
|
1831
|
-
autoStart?: boolean;
|
|
1832
|
-
};
|
|
1833
|
-
}
|
|
1834
|
-
interface IssuerService {
|
|
1835
|
-
/** AuthService — login, logout, nonce management. */
|
|
1836
|
-
auth: AuthService;
|
|
1837
|
-
/** Session store — nonce + JWT session persistence. */
|
|
1838
|
-
session: ISessionStore;
|
|
1839
|
-
ledger: IPointLedger;
|
|
1840
|
-
policy: IPolicyEngine;
|
|
1841
|
-
/** RelayService — prepareMint / prepareBurn UserOp builders. */
|
|
1842
|
-
relay: RelayService;
|
|
1843
|
-
/** FeeManager — gas fee estimation. Undefined if not configured. */
|
|
1844
|
-
fee: FeeManager | undefined;
|
|
1845
|
-
/** All indexers keyed by PointToken address. */
|
|
1846
|
-
indexers: Map<Address, PointIndexer>;
|
|
1847
|
-
/**
|
|
1848
|
-
* First indexer. Kept for backward compat with 0.1.x callers.
|
|
1849
|
-
* @deprecated use `indexers.get(tokenAddress)` for multi-token.
|
|
1850
|
-
*/
|
|
1851
|
-
indexer: PointIndexer;
|
|
1852
|
-
/** Framework-agnostic HTTP handlers — wire into Express / Fastify / Hono. */
|
|
1853
|
-
api: IssuerApiHandlers;
|
|
1854
|
-
}
|
|
1855
|
-
/**
|
|
1856
|
-
* Wire a fully-functional issuer service from a single config object.
|
|
1857
|
-
*
|
|
1858
|
-
* Defaults:
|
|
1859
|
-
* - `sessionStore` → `MemorySessionStore` (dev/test only — replace in prod)
|
|
1860
|
-
* - `policy` → `DefaultPolicyEngine({ ledger })`
|
|
1861
|
-
* - `feeManager` → undefined (handleGasFee throws until configured)
|
|
1862
|
-
* - `poolsProvider` → undefined (handlePools throws until configured)
|
|
1863
|
-
* - `indexer.autoStart` → false
|
|
1864
|
-
*
|
|
1865
|
-
* Throws synchronously if any required field is missing.
|
|
1866
|
-
*/
|
|
1867
|
-
declare function createIssuerService(config: IssuerServiceConfig): IssuerService;
|
|
1868
|
-
|
|
1869
|
-
/**
|
|
1870
|
-
* A pending UserOp serialized for persistent storage (Redis, Postgres, memory).
|
|
1871
|
-
*
|
|
1872
|
-
* All bigint fields are stored as decimal strings so the entry can be
|
|
1873
|
-
* JSON-serialized without precision loss. Convert back to bigint before
|
|
1874
|
-
* calling `computeUserOpHash` or `serializeUserOpToJsonRpc`.
|
|
1875
|
-
*/
|
|
1876
|
-
interface PendingUserOpEntry {
|
|
1877
|
-
sender: Address;
|
|
1878
|
-
nonce: string;
|
|
1879
|
-
callData: Hex;
|
|
1880
|
-
callGasLimit: string;
|
|
1881
|
-
verificationGasLimit: string;
|
|
1882
|
-
preVerificationGas: string;
|
|
1883
|
-
maxFeePerGas: string;
|
|
1884
|
-
maxPriorityFeePerGas: string;
|
|
1885
|
-
paymaster?: Address;
|
|
1886
|
-
paymasterVerificationGasLimit?: string;
|
|
1887
|
-
paymasterPostOpGasLimit?: string;
|
|
1888
|
-
paymasterData?: Hex;
|
|
1889
|
-
chainId: number;
|
|
1890
|
-
/** Hex-encoded userOpHash — the value the user signed via personal_sign. */
|
|
1891
|
-
userOpHash: Hex;
|
|
1892
|
-
/**
|
|
1893
|
-
* Fee-stripped fallback variant. Set by `/claim/prepare` and
|
|
1894
|
-
* `/redeem/prepare` when a PT operator fee is configured AND the
|
|
1895
|
-
* paymaster sponsorship attached successfully — i.e. the user might
|
|
1896
|
-
* still want to submit without paymaster (paying ETH gas), and in
|
|
1897
|
-
* that case shouldn't be charged the PT fee. `/claim/submit` reads
|
|
1898
|
-
* this branch when its request body specifies
|
|
1899
|
-
* `variant: "fallback"`.
|
|
1900
|
-
*
|
|
1901
|
-
* Has a different `callData` (no PT.transfer prepended) and
|
|
1902
|
-
* therefore a different `userOpHash`. Paymaster fields are NOT
|
|
1903
|
-
* present — the fallback is by definition unsponsored.
|
|
1904
|
-
*/
|
|
1905
|
-
fallback?: {
|
|
1906
|
-
callData: Hex;
|
|
1907
|
-
callGasLimit: string;
|
|
1908
|
-
verificationGasLimit: string;
|
|
1909
|
-
preVerificationGas: string;
|
|
1910
|
-
userOpHash: Hex;
|
|
1911
|
-
};
|
|
1912
|
-
}
|
|
1913
|
-
/**
|
|
1914
|
-
* Storage backend for pending UserOps in the mobile prepare/submit pattern.
|
|
1915
|
-
*
|
|
1916
|
-
* Implement this interface and wire it into your issuer backend:
|
|
1917
|
-
* - `save()` — called by `POST /claim/prepare` and `POST /redeem/prepare`
|
|
1918
|
-
* - `get()` — called by `POST /claim/submit` and `POST /redeem/submit`
|
|
1919
|
-
* - `delete()` — called after successful submit or explicit cancellation
|
|
1920
|
-
*
|
|
1921
|
-
* The default implementation in the gg56 boilerplate uses Redis with
|
|
1922
|
-
* a short TTL matching the MintRequest / BurnRequest deadline.
|
|
1923
|
-
*/
|
|
1924
|
-
interface IPendingUserOpStore {
|
|
1925
|
-
save(lockId: string, entry: PendingUserOpEntry, ttlSeconds: number): Promise<void>;
|
|
1926
|
-
get(lockId: string): Promise<PendingUserOpEntry | null>;
|
|
1927
|
-
delete(lockId: string): Promise<void>;
|
|
1928
|
-
}
|
|
1929
|
-
|
|
1930
|
-
/**
|
|
1931
|
-
* Convert a stored `PendingUserOpEntry` (decimal-string fields) plus a
|
|
1932
|
-
* signature into the JSON-RPC wire format for `eth_sendUserOperation`.
|
|
1933
|
-
*
|
|
1934
|
-
* Bridges the gap between the serialized storage format (decimal strings,
|
|
1935
|
-
* safe for JSON/Redis) and `serializeUserOpToJsonRpc` which expects bigints.
|
|
1936
|
-
*/
|
|
1937
|
-
declare function serializeEntryToJsonRpc(entry: PendingUserOpEntry, signature: Hex, variant?: "sponsored" | "fallback"): Record<string, string | null>;
|
|
1938
|
-
|
|
1939
|
-
/**
|
|
1940
|
-
* Re-shape `UserOpTypedData` so all `bigint` fields become hex strings —
|
|
1941
|
-
* required for JSON transport over HTTP. Mirrors the inverse of what
|
|
1942
|
-
* `walletClient.signTypedData` accepts on the client (it auto-coerces hex
|
|
1943
|
-
* strings back to bigints for `uint256` fields).
|
|
1944
|
-
*/
|
|
1945
|
-
type SerializedUserOpTypedData = {
|
|
1946
|
-
domain: UserOpTypedData["domain"];
|
|
1947
|
-
types: UserOpTypedData["types"];
|
|
1948
|
-
primaryType: UserOpTypedData["primaryType"];
|
|
1949
|
-
message: {
|
|
1950
|
-
sender: Address;
|
|
1951
|
-
nonce: Hex;
|
|
1952
|
-
initCode: Hex;
|
|
1953
|
-
callData: Hex;
|
|
1954
|
-
accountGasLimits: Hex;
|
|
1955
|
-
preVerificationGas: Hex;
|
|
1956
|
-
gasFees: Hex;
|
|
1957
|
-
paymasterAndData: Hex;
|
|
1958
|
-
};
|
|
1959
|
-
};
|
|
1960
|
-
/**
|
|
1961
|
-
* Convert a `UserOpTypedData` payload into the JSON-safe wire form
|
|
1962
|
-
* (bigint → hex string). The mobile client passes this directly to
|
|
1963
|
-
* `eth_signTypedData_v4` / viem's `signTypedData`.
|
|
1964
|
-
*/
|
|
1965
|
-
declare function serializeUserOpTypedData(td: UserOpTypedData): SerializedUserOpTypedData;
|
|
1966
|
-
/**
|
|
1967
|
-
* Merge Pimlico's paymaster-sponsorship response into a UserOp
|
|
1968
|
-
* skeleton, applying only fields that are actually defined.
|
|
1628
|
+
* Merge Pimlico's paymaster-sponsorship response into a UserOp
|
|
1629
|
+
* skeleton, applying only fields that are actually defined.
|
|
1969
1630
|
*
|
|
1970
1631
|
* `pm_sponsorUserOperation` returns:
|
|
1971
1632
|
* - `paymaster` / `paymasterData` — required for the sponsored sig
|
|
@@ -2052,129 +1713,875 @@ interface PrepareMobileUserOpParams {
|
|
|
2052
1713
|
/** TTL the store entry should outlive — typically the MintRequest deadline. */
|
|
2053
1714
|
ttlSeconds: number;
|
|
2054
1715
|
}
|
|
2055
|
-
interface PrepareMobileUserOpResult {
|
|
2056
|
-
sponsored: PreparedUserOp;
|
|
2057
|
-
/**
|
|
2058
|
-
* Set when `partialUserOpFallback` was supplied AND the PT fee was
|
|
2059
|
-
* non-zero (i.e. sponsored ≠ fallback). Mobile client picks which
|
|
2060
|
-
* variant to sign + submit; SDK's `serializeEntryToJsonRpc` reads
|
|
2061
|
-
* the `variant` flag to dispatch.
|
|
2062
|
-
*/
|
|
2063
|
-
fallback?: PreparedUserOp;
|
|
2064
|
-
/** What got persisted into the pending-userop store. */
|
|
2065
|
-
entry: PendingUserOpEntry;
|
|
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.
|
|
1731
|
+
*
|
|
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.
|
|
1743
|
+
*
|
|
1744
|
+
* Replaces ~100 LoC of glue per scenario in issuer controllers.
|
|
1745
|
+
*/
|
|
1746
|
+
declare function prepareMobileUserOp(params: PrepareMobileUserOpParams): Promise<PrepareMobileUserOpResult>;
|
|
1747
|
+
|
|
1748
|
+
/**
|
|
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:
|
|
1752
|
+
*
|
|
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.
|
|
1758
|
+
*/
|
|
1759
|
+
declare class PendingUserOpNotFoundError extends Error {
|
|
1760
|
+
readonly code = "PENDING_USEROP_NOT_FOUND";
|
|
1761
|
+
constructor(lockId: string);
|
|
1762
|
+
}
|
|
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;
|
|
1788
|
+
provider: PublicClient;
|
|
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;
|
|
1805
|
+
}
|
|
1806
|
+
/**
|
|
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.
|
|
1839
|
+
*
|
|
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.
|
|
1883
|
+
*
|
|
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.
|
|
1897
|
+
*/
|
|
1898
|
+
declare class IssuerStateValidator {
|
|
1899
|
+
private readonly provider;
|
|
1900
|
+
private readonly registryAddress;
|
|
1901
|
+
private readonly pointTokenIssuerCache;
|
|
1902
|
+
private readonly stateCache;
|
|
1903
|
+
private readonly inflight;
|
|
1904
|
+
constructor(provider: PublicClient, registryAddress: Address);
|
|
1905
|
+
/**
|
|
1906
|
+
* Convenience factory — reads `registryAddress` from the SDK
|
|
1907
|
+
* `CONTRACT_ADDRESSES` map for the given chain.
|
|
1908
|
+
*/
|
|
1909
|
+
static forChain(provider: PublicClient, chainId: number): IssuerStateValidator;
|
|
1910
|
+
/**
|
|
1911
|
+
* Invalidate cached state for one PointToken, or everything if omitted.
|
|
1912
|
+
* Call after admin txs that change registry or cap settings.
|
|
1913
|
+
*/
|
|
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;
|
|
1938
|
+
}
|
|
1939
|
+
|
|
1940
|
+
type DecodedCall$2 = ReturnType<typeof decodeBatchExecuteCalls>[number];
|
|
1941
|
+
|
|
1942
|
+
/**
|
|
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.
|
|
1953
|
+
*/
|
|
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);
|
|
1958
|
+
}
|
|
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;
|
|
1980
|
+
}
|
|
1981
|
+
interface PTClaimRequest {
|
|
1982
|
+
authenticatedAddress: Address;
|
|
1983
|
+
userAddress: Address;
|
|
1984
|
+
amount: bigint;
|
|
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;
|
|
1995
|
+
/**
|
|
1996
|
+
* Fallback UserOp — mint only, no PT fee transfer. Present only when
|
|
1997
|
+
* `feeAmount > 0`. User pays gas in ETH directly.
|
|
1998
|
+
*/
|
|
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[];
|
|
2008
|
+
}
|
|
2009
|
+
declare class PTClaimHandler {
|
|
2010
|
+
private readonly cfg;
|
|
2011
|
+
constructor(config: PTClaimHandlerConfig);
|
|
2012
|
+
handle(request: PTClaimRequest): Promise<PTClaimResponse>;
|
|
2013
|
+
}
|
|
2014
|
+
|
|
2015
|
+
type DecodedCall$1 = ReturnType<typeof decodeBatchExecuteCalls>[number];
|
|
2016
|
+
|
|
2017
|
+
/**
|
|
2018
|
+
* PT → USDT swap handler.
|
|
2019
|
+
*
|
|
2020
|
+
* Quotes via V4 on-chain Quoter (`findBestQuote`), applies slippage,
|
|
2021
|
+
* computes the PT gas-reimbursement fee from `FeeManager`, and builds
|
|
2022
|
+
* two UserOps:
|
|
2023
|
+
*
|
|
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.
|
|
2036
|
+
*/
|
|
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];
|
|
2090
|
+
|
|
2091
|
+
/**
|
|
2092
|
+
* Orderly perp-deposit handler — builds the sponsored + fallback
|
|
2093
|
+
* UserOps for the PAFI Relay path.
|
|
2094
|
+
*
|
|
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:
|
|
2098
|
+
*
|
|
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`).
|
|
2107
|
+
*/
|
|
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 {
|
|
2113
|
+
provider: PublicClient;
|
|
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;
|
|
2118
|
+
/**
|
|
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.
|
|
2122
|
+
*/
|
|
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 {
|
|
2157
|
+
/**
|
|
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.
|
|
2161
|
+
*/
|
|
2162
|
+
subgraphUrl?: string;
|
|
2163
|
+
/**
|
|
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.
|
|
2167
|
+
*/
|
|
2168
|
+
cacheTtlMs?: number;
|
|
2169
|
+
/**
|
|
2170
|
+
* Optional fetch override for test harnesses. Defaults to global `fetch`.
|
|
2171
|
+
*/
|
|
2172
|
+
fetchImpl?: typeof fetch;
|
|
2173
|
+
/**
|
|
2174
|
+
* Optional clock override for tests.
|
|
2175
|
+
*/
|
|
2176
|
+
now?: () => number;
|
|
2177
|
+
}
|
|
2178
|
+
/**
|
|
2179
|
+
* Create a `PoolsProvider` backed by the PAFI subgraph.
|
|
2180
|
+
*
|
|
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.
|
|
2184
|
+
*
|
|
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
|
+
* ```
|
|
2209
|
+
*/
|
|
2210
|
+
declare function createSubgraphPoolsProvider(config?: SubgraphPoolsProviderConfig): PoolsProvider;
|
|
2211
|
+
|
|
2212
|
+
/**
|
|
2213
|
+
* Config for `createSubgraphNativeUsdtQuoter`.
|
|
2214
|
+
*/
|
|
2215
|
+
interface SubgraphNativeUsdtQuoterConfig {
|
|
2216
|
+
/**
|
|
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.
|
|
2220
|
+
*/
|
|
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;
|
|
2251
|
+
}
|
|
2252
|
+
/**
|
|
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.
|
|
2258
|
+
*
|
|
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.
|
|
2263
|
+
*
|
|
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
|
+
* ```
|
|
2281
|
+
*/
|
|
2282
|
+
declare function createSubgraphNativeUsdtQuoter(config?: SubgraphNativeUsdtQuoterConfig): (amountNative: bigint) => Promise<bigint>;
|
|
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
|
+
}
|
|
2302
|
+
/**
|
|
2303
|
+
* Create a native→PT quoter for use as `FeeManager.quoteNativeToFee`.
|
|
2304
|
+
*
|
|
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
|
+
* ```
|
|
2323
|
+
*/
|
|
2324
|
+
declare function createNativePtQuoter(config: NativePtQuoterConfig): (amountNative: bigint) => Promise<bigint>;
|
|
2325
|
+
|
|
2326
|
+
/**
|
|
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)
|
|
2332
|
+
*/
|
|
2333
|
+
interface CombinedBalance {
|
|
2334
|
+
offChain: bigint;
|
|
2335
|
+
onChain: bigint;
|
|
2336
|
+
total: bigint;
|
|
2337
|
+
}
|
|
2338
|
+
interface BalanceAggregatorConfig {
|
|
2339
|
+
provider: PublicClient;
|
|
2340
|
+
ledger: IPointLedger;
|
|
2066
2341
|
}
|
|
2067
2342
|
/**
|
|
2068
|
-
*
|
|
2069
|
-
*
|
|
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
|
-
* 2. Compute the EIP-712 userOpHash + the typed-data payload (in
|
|
2075
|
-
* JSON-safe form for HTTP transport).
|
|
2076
|
-
* 3. (Optional) Repeat for the `partialUserOpFallback` skeleton with
|
|
2077
|
-
* no paymaster fields — produces a separate hash + typed-data so
|
|
2078
|
-
* the client can re-sign if it falls back.
|
|
2079
|
-
* 4. Persist a single store entry containing BOTH callData variants
|
|
2080
|
-
* keyed by lockId. `serializeEntryToJsonRpc` reads the `variant`
|
|
2081
|
-
* param at submit time.
|
|
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).
|
|
2082
2349
|
*
|
|
2083
|
-
*
|
|
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."
|
|
2084
2352
|
*/
|
|
2085
|
-
declare
|
|
2353
|
+
declare class BalanceAggregator {
|
|
2354
|
+
private readonly provider;
|
|
2355
|
+
private readonly ledger;
|
|
2356
|
+
constructor(config: BalanceAggregatorConfig);
|
|
2357
|
+
/**
|
|
2358
|
+
* Combined balance for a single (user, token) pair. Fetches off-chain
|
|
2359
|
+
* + on-chain in parallel.
|
|
2360
|
+
*/
|
|
2361
|
+
getCombinedBalance(user: Address, pointToken: Address): Promise<CombinedBalance>;
|
|
2362
|
+
/**
|
|
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).
|
|
2366
|
+
*/
|
|
2367
|
+
getCombinedBalanceMulti(user: Address, pointTokens: Address[]): Promise<Map<Address, CombinedBalance>>;
|
|
2368
|
+
}
|
|
2086
2369
|
|
|
2087
|
-
|
|
2088
|
-
|
|
2089
|
-
|
|
2090
|
-
|
|
2091
|
-
|
|
2092
|
-
|
|
2093
|
-
|
|
2094
|
-
|
|
2095
|
-
|
|
2096
|
-
mintingOracle: Address;
|
|
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();
|
|
2097
2379
|
}
|
|
2098
|
-
|
|
2099
|
-
|
|
2100
|
-
|
|
2101
|
-
|
|
2102
|
-
|
|
2103
|
-
|
|
2104
|
-
|
|
2105
|
-
|
|
2106
|
-
|
|
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;
|
|
2403
|
+
/**
|
|
2404
|
+
* Function name to surface in audit / paymaster context. Defaults to
|
|
2405
|
+
* a per-scenario sensible value (`mint` / `burn` / `swap` / generic
|
|
2406
|
+
* scenario name).
|
|
2407
|
+
*/
|
|
2408
|
+
functionName?: string;
|
|
2409
|
+
/** Optional logger for the "sponsorship declined" warning. */
|
|
2410
|
+
onWarning?: (msg: string) => void;
|
|
2107
2411
|
}
|
|
2108
2412
|
/**
|
|
2109
|
-
*
|
|
2110
|
-
*
|
|
2413
|
+
* Thin wrapper around `PafiBackendClient.requestSponsorship` with the
|
|
2414
|
+
* "non-fatal on failure" semantics every issuer wants:
|
|
2415
|
+
*
|
|
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.
|
|
2423
|
+
*
|
|
2424
|
+
* Replaces ~30 LoC of try/catch + scenario-to-function mapping every
|
|
2425
|
+
* issuer would copy.
|
|
2111
2426
|
*/
|
|
2112
|
-
declare
|
|
2113
|
-
|
|
2114
|
-
|
|
2115
|
-
|
|
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
|
+
};
|
|
2116
2442
|
}
|
|
2443
|
+
/**
|
|
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.).
|
|
2457
|
+
*/
|
|
2458
|
+
declare function relayUserOp(params: RelayUserOpParams): Promise<{
|
|
2459
|
+
userOpHash: Hex;
|
|
2460
|
+
}>;
|
|
2117
2461
|
|
|
2118
2462
|
/**
|
|
2119
|
-
*
|
|
2120
|
-
*
|
|
2121
|
-
* Reads IssuerRegistry + PointToken on-chain state and pre-validates
|
|
2122
|
-
* mint requests before the user submits a UserOp. Catching these
|
|
2123
|
-
* off-chain lets issuers fail fast with a clear error rather than
|
|
2124
|
-
* wasting gas on a revert.
|
|
2463
|
+
* Top-level configuration for `createIssuerService`.
|
|
2125
2464
|
*
|
|
2126
|
-
*
|
|
2127
|
-
*
|
|
2128
|
-
*
|
|
2129
|
-
*
|
|
2130
|
-
* (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.
|
|
2131
2469
|
*
|
|
2132
|
-
*
|
|
2133
|
-
*
|
|
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.
|
|
2134
2474
|
*/
|
|
2135
|
-
|
|
2136
|
-
|
|
2137
|
-
|
|
2138
|
-
|
|
2139
|
-
|
|
2140
|
-
|
|
2141
|
-
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[];
|
|
2142
2481
|
/**
|
|
2143
|
-
*
|
|
2144
|
-
*
|
|
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.
|
|
2145
2486
|
*/
|
|
2146
|
-
|
|
2487
|
+
contracts?: Pick<ApiConfigResponse["contracts"], "pointToken" | "pointTokens" | "relay">;
|
|
2147
2488
|
/**
|
|
2148
|
-
*
|
|
2149
|
-
*
|
|
2489
|
+
* Shared `PublicClient` used for on-chain reads, simulation, indexer
|
|
2490
|
+
* polling, and gas-price lookups. Must be pointed at the target chain.
|
|
2150
2491
|
*/
|
|
2151
|
-
|
|
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
|
+
};
|
|
2152
2500
|
/**
|
|
2153
|
-
*
|
|
2154
|
-
*
|
|
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.
|
|
2155
2506
|
*/
|
|
2156
|
-
|
|
2507
|
+
ledger: IPointLedger;
|
|
2157
2508
|
/**
|
|
2158
|
-
*
|
|
2159
|
-
*
|
|
2509
|
+
* Policy engine — optional, defaults to `DefaultPolicyEngine` which checks
|
|
2510
|
+
* off-chain balance. Extend or replace to add KYC, volume caps, etc.
|
|
2160
2511
|
*/
|
|
2161
|
-
|
|
2512
|
+
policy?: IPolicyEngine;
|
|
2513
|
+
/** Session store — optional, defaults to `MemorySessionStore` (dev/test only). */
|
|
2514
|
+
sessionStore?: ISessionStore;
|
|
2162
2515
|
/**
|
|
2163
|
-
*
|
|
2164
|
-
*
|
|
2165
|
-
* Throws `IssuerStateError` with:
|
|
2166
|
-
* - `ISSUER_NOT_REGISTERED` — registry has no record for this issuer
|
|
2167
|
-
* - `ISSUER_INACTIVE` — issuer.active is false
|
|
2168
|
-
* - `MINT_CAP_EXCEEDED` — totalSupply + amount would exceed hardCap
|
|
2169
|
-
*
|
|
2170
|
-
* Returns the fetched state on success so callers can log without a
|
|
2171
|
-
* second RPC round-trip.
|
|
2516
|
+
* Fee management config. If omitted the `handleGasFee` endpoint will
|
|
2517
|
+
* throw "not configured" at request time.
|
|
2172
2518
|
*/
|
|
2173
|
-
|
|
2174
|
-
|
|
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;
|
|
2175
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;
|
|
2176
2583
|
|
|
2177
2584
|
/** SDK package version — bumped on every release */
|
|
2178
2585
|
declare const PAFI_ISSUER_SDK_VERSION = "0.4.0";
|
|
2179
2586
|
|
|
2180
|
-
export { type ApiClaimRequest, type ApiClaimResponse, type ApiConfigResponse, type ApiGasFeeResponse, type ApiLoginRequest, type ApiLoginResponse, type ApiNonceResponse, type ApiPoolsRequest, type ApiPoolsResponse, type ApiRedeemRequest, type ApiRedeemResponse, type ApiTopUpRequest, type ApiTopUpResponse, type ApiUserRequest, type ApiUserResponse, type AuthContext, AuthError, type AuthErrorCode, AuthService, type AuthServiceConfig, BalanceAggregator, type BalanceAggregatorConfig, type BurnEvent, BurnIndexer, type BurnIndexerConfig, type BurnStatusParams, type BurnStatusResponse, type CombinedBalance, DefaultPolicyEngine, type DefaultPolicyEngineOptions, FeeManager, type FeeManagerConfig, type IIndexerCursorStore, type IPendingUserOpStore, type IPointLedger, type IPolicyEngine, type ISessionStore, InMemoryCursorStore, IssuerApiHandlers, type IssuerApiHandlersConfig, type IssuerRegistryRecord, type IssuerService, type IssuerServiceConfig, IssuerStateError, IssuerStateValidator, LockNotFoundError, type LockedMintRequest, type LoginResult, MemorySessionStore, type MemorySessionStoreOptions, type MintEvent, type MintStatusParams, type MintStatusResponse, type MintingStatus, type NativePtQuoterConfig, NonceManager, PAFI_ISSUER_SDK_VERSION, PTRedeemError, PTRedeemHandler, type PTRedeemHandlerConfig, type PTRedeemRequest, type PTRedeemResponse, PafiBackendClient, type PafiBackendConfig, PafiBackendError, type PafiBackendErrorCode, type PendingCredit, type PendingUserOpEntry, PointIndexer, type PointIndexerConfig, type PolicyDecision, type PolicyEvalRequest, type PoolsProvider, type PreValidateMintResult, type PrepareBurnDirectParams, type PrepareBurnParams, type PrepareBurnWithSigParams, type PrepareMintParams, type PrepareMobileUserOpParams, type PrepareMobileUserOpResult, type PreparedUserOp, RelayError, type RelayErrorCode, RelayService, type RelayUserOpRequest, type RelayUserOpResponse, type RetryConfig, type SerializedUserOpTypedData, type Session, type SponsorshipRequest, type SponsorshipResponse, type SponsorshipTarget, type SponsorshipUserOp, type SubgraphNativeUsdtQuoterConfig, type SubgraphPoolsProviderConfig, TopUpRedemptionError, TopUpRedemptionHandler, type TopUpRedemptionHandlerConfig, type TopUpRedemptionRequest, type TopUpRedemptionResponse, authenticateRequest, createIssuerService, createNativePtQuoter, createSubgraphNativeUsdtQuoter, createSubgraphPoolsProvider, handleClaimStatus, handleRedeemStatus, mergePaymasterFields, prepareMobileUserOp, serializeEntryToJsonRpc, serializeUserOpTypedData };
|
|
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 };
|