@pafi-dev/issuer 0.13.0 → 0.15.0
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/README.md +14 -54
- package/dist/index.cjs +106 -144
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +139 -129
- package/dist/index.d.ts +139 -129
- package/dist/index.js +92 -132
- package/dist/index.js.map +1 -1
- package/package.json +4 -2
package/dist/index.d.cts
CHANGED
|
@@ -115,8 +115,18 @@ interface IPointLedger {
|
|
|
115
115
|
/** List currently-pending locked mint requests for a user. */
|
|
116
116
|
getLockedRequests(userAddress: Address, tokenAddress?: Address): Promise<LockedMintRequest[]>;
|
|
117
117
|
/**
|
|
118
|
-
* Transition a lock to a
|
|
118
|
+
* Transition a lock from `PENDING` to a terminal status
|
|
119
|
+
* (`MINTED` | `EXPIRED` | `FAILED`). The on-chain tx hash is
|
|
119
120
|
* supplied when the status is `MINTED`.
|
|
121
|
+
*
|
|
122
|
+
* Terminal states are immutable: once a lock leaves `PENDING` the
|
|
123
|
+
* status is fixed. Calling `updateMintStatus` on a non-PENDING lock
|
|
124
|
+
* is a silent no-op. This protects against late-arriving writes from
|
|
125
|
+
* different code paths (e.g. PointIndexer.finalize and the bundler-
|
|
126
|
+
* receipt fallback in statusHandlers) racing to overwrite each
|
|
127
|
+
* other — particularly the case where a stale `EXPIRED`/`FAILED`
|
|
128
|
+
* write would corrupt a `MINTED` lock whose balance has already
|
|
129
|
+
* been deducted.
|
|
120
130
|
*/
|
|
121
131
|
updateMintStatus(lockId: string, status: MintingStatus, txHash?: Hex): Promise<void>;
|
|
122
132
|
/**
|
|
@@ -204,7 +214,7 @@ interface DefaultPolicyEngineOptions {
|
|
|
204
214
|
provider?: PublicClient;
|
|
205
215
|
mintingOracleAddress?: Address;
|
|
206
216
|
/**
|
|
207
|
-
* Override the on-chain cap check. Defaults to `@pafi/core`'s
|
|
217
|
+
* Override the on-chain cap check. Defaults to `@pafi-dev/core`'s
|
|
208
218
|
* `verifyMintCap`, which reverts if the issuer's declared supply would
|
|
209
219
|
* be exceeded. A rejected check should throw; returning normally is pass.
|
|
210
220
|
*/
|
|
@@ -561,7 +571,7 @@ interface RelayServiceConfig {
|
|
|
561
571
|
chainId?: number;
|
|
562
572
|
}
|
|
563
573
|
/**
|
|
564
|
-
* Builds unsigned `PartialUserOperation` payloads for the
|
|
574
|
+
* Builds unsigned `PartialUserOperation` payloads for the sponsored
|
|
565
575
|
* flow. The service is stateless and HTTP-client-free:
|
|
566
576
|
*
|
|
567
577
|
* - `prepareMint` signs a `MintRequest` EIP-712 with the caller-supplied
|
|
@@ -573,7 +583,7 @@ interface RelayServiceConfig {
|
|
|
573
583
|
* deadline, burnerSig)`.
|
|
574
584
|
*
|
|
575
585
|
* There is no broadcasting, no operator wallet, no simulation — those
|
|
576
|
-
* concerns
|
|
586
|
+
* concerns live in the Bundler + Paymaster.
|
|
577
587
|
*/
|
|
578
588
|
declare class RelayService {
|
|
579
589
|
private readonly provider;
|
|
@@ -607,13 +617,13 @@ declare class RelayService {
|
|
|
607
617
|
* provides a pre-signed `BurnRequest` + sig bytes (typically from
|
|
608
618
|
* `PTRedeemHandler`).
|
|
609
619
|
*
|
|
610
|
-
* Direct burn (no sig)
|
|
611
|
-
*
|
|
620
|
+
* Direct burn (no sig) is not used — every burn goes through the
|
|
621
|
+
* issuer-signed `BurnRequest` path.
|
|
612
622
|
*/
|
|
613
623
|
prepareBurn(params: PrepareBurnParams): Promise<PartialUserOperation>;
|
|
614
624
|
}
|
|
615
625
|
/**
|
|
616
|
-
*
|
|
626
|
+
* Sig-gated `PointToken.mint(to, amount, deadline, minterSig)`.
|
|
617
627
|
*
|
|
618
628
|
* The issuer backend validates off-chain (balance, policy, KYC), signs
|
|
619
629
|
* a `MintRequest` EIP-712 with its minter signer, and packages the
|
|
@@ -645,16 +655,16 @@ interface PrepareMintParams {
|
|
|
645
655
|
/** Unix timestamp after which the signature expires. */
|
|
646
656
|
deadline: bigint;
|
|
647
657
|
/**
|
|
648
|
-
* Optional
|
|
658
|
+
* Optional — when set, mint is routed through MintFeeWrapper:
|
|
649
659
|
* - sig.receiver = wrapper address (vs `userAddress` for direct path)
|
|
650
660
|
* - calldata target = wrapper.mintWithFee(pointToken, user, gross, ...)
|
|
651
661
|
* - the wrapper then mints `amount` to itself, splits per recipient list,
|
|
652
662
|
* and forwards net to the user.
|
|
653
663
|
*
|
|
654
|
-
* Leave undefined
|
|
655
|
-
*
|
|
656
|
-
*
|
|
657
|
-
*
|
|
664
|
+
* Leave undefined for direct-mint behavior (no fee skim). Wrapper
|
|
665
|
+
* must be registered on the PointToken via `IssuerRegistry.addIssuer`
|
|
666
|
+
* cascade (or owner-only `wrapper.registerToken`) before this path
|
|
667
|
+
* works on-chain.
|
|
658
668
|
*/
|
|
659
669
|
mintFeeWrapperAddress?: Address;
|
|
660
670
|
/**
|
|
@@ -669,11 +679,10 @@ interface PrepareMintParams {
|
|
|
669
679
|
preVerificationGas?: bigint;
|
|
670
680
|
}
|
|
671
681
|
/**
|
|
672
|
-
*
|
|
673
|
-
*
|
|
674
|
-
*
|
|
675
|
-
*
|
|
676
|
-
* branched on internally.
|
|
682
|
+
* Sig-gated burn only — every burn goes through `BurnRequest` EIP-712
|
|
683
|
+
* signed by the issuer burner. The `mode: 'burnWithSig'` discriminant
|
|
684
|
+
* is preserved for backwards-compat with existing callers but is no
|
|
685
|
+
* longer branched on internally.
|
|
677
686
|
*/
|
|
678
687
|
interface PrepareBurnParams {
|
|
679
688
|
userAddress: Address;
|
|
@@ -715,8 +724,8 @@ interface FeeManagerConfig {
|
|
|
715
724
|
gasPremiumBps?: number;
|
|
716
725
|
/**
|
|
717
726
|
* Quote function — given an amount of native wei, return the
|
|
718
|
-
* equivalent amount in the fee currency (PT raw units
|
|
719
|
-
* USDT 6-decimal
|
|
727
|
+
* equivalent amount in the fee currency (typically PT raw units;
|
|
728
|
+
* USDT 6-decimal for swap / perp deposit flows).
|
|
720
729
|
*
|
|
721
730
|
* Injected so the manager stays chain- and token-agnostic. Issuers
|
|
722
731
|
* wire it to `@pafi-dev/core` V4 quoting, a subgraph query, or an
|
|
@@ -728,18 +737,14 @@ interface FeeManagerConfig {
|
|
|
728
737
|
* Computes how much fee to collect from the user to cover the gas cost
|
|
729
738
|
* of a sponsored UserOp.
|
|
730
739
|
*
|
|
731
|
-
*
|
|
732
|
-
*
|
|
733
|
-
* The fee is now expressed in the **fee currency** chosen by the caller
|
|
734
|
-
* (PT for mint/burn, USDT for swap/perp_deposit) — not hardcoded to USDT.
|
|
740
|
+
* The fee is expressed in the **fee currency** chosen by the caller
|
|
741
|
+
* (PT for mint/burn, USDT for swap/perp_deposit) — not hardcoded.
|
|
735
742
|
*
|
|
736
|
-
* **
|
|
737
|
-
*
|
|
738
|
-
*
|
|
743
|
+
* **No operator rebalancing.** The operator does not hold ETH directly;
|
|
744
|
+
* gas is paid by PAFI sponsor-relayer via the paymaster-proxy (see
|
|
745
|
+
* [SPONSORED_PATH_FLOW.md]). The fee collected here is an
|
|
739
746
|
* application-level ERC-20 transfer inside the same UserOp batch, not a
|
|
740
747
|
* reimbursement to a wallet that needs topping up.
|
|
741
|
-
*
|
|
742
|
-
* `rebalanceIfNeeded()` and `swapUsdtToNative` were removed in 0.3.0.
|
|
743
748
|
*/
|
|
744
749
|
declare class FeeManager {
|
|
745
750
|
private readonly provider;
|
|
@@ -815,8 +820,9 @@ interface PointIndexerConfig {
|
|
|
815
820
|
pointTokenAddress: Address;
|
|
816
821
|
ledger: IPointLedger;
|
|
817
822
|
/**
|
|
818
|
-
*
|
|
819
|
-
* (filtered by this `pointToken`) instead of
|
|
823
|
+
* When set, indexer listens to `MintFeeWrapper.MintWithFee`
|
|
824
|
+
* (filtered by this `pointToken`) instead of
|
|
825
|
+
* `PointToken.Transfer(0x0)`.
|
|
820
826
|
*
|
|
821
827
|
* Required for wrapper-mediated mints because the on-chain Transfer
|
|
822
828
|
* destination is the wrapper itself (not the end user), so a naive
|
|
@@ -874,15 +880,15 @@ interface PointIndexerConfig {
|
|
|
874
880
|
*
|
|
875
881
|
* **Two modes** — selected at construction by `mintFeeWrapperAddress`:
|
|
876
882
|
*
|
|
877
|
-
* 1. **Wrapper mode (
|
|
883
|
+
* 1. **Wrapper mode (recommended for mainnet)**
|
|
878
884
|
* Listens to `MintFeeWrapper.MintWithFee(indexed pointToken, indexed to,
|
|
879
885
|
* grossAmount, netAmount, feeAmount)` filtered by `pointToken`. The
|
|
880
886
|
* `to` field is the actual end-user (not the wrapper), and `grossAmount`
|
|
881
887
|
* matches the off-chain lock's amount.
|
|
882
888
|
*
|
|
883
|
-
* 2. **Direct mode (
|
|
884
|
-
* Listens to `PointToken.Transfer(from=0x0 → to)
|
|
885
|
-
*
|
|
889
|
+
* 2. **Direct mode (chains without wrapper)**
|
|
890
|
+
* Listens to `PointToken.Transfer(from=0x0 → to)`. Used when the
|
|
891
|
+
* wrapper address is undefined / zero / dead.
|
|
886
892
|
*
|
|
887
893
|
* Finalization strategy (per event):
|
|
888
894
|
* 1. Find a PENDING locked mint request for `to` with matching amount.
|
|
@@ -934,7 +940,7 @@ declare class PointIndexer {
|
|
|
934
940
|
*/
|
|
935
941
|
processBlockRange(from: bigint, to: bigint): Promise<void>;
|
|
936
942
|
/**
|
|
937
|
-
* Wrapper mode
|
|
943
|
+
* Wrapper mode: listen for `MintWithFee` on the wrapper,
|
|
938
944
|
* filtered to events for THIS pointToken only. The event's `to` field
|
|
939
945
|
* is the actual end user, and `grossAmount` matches the lock amount.
|
|
940
946
|
*/
|
|
@@ -1079,22 +1085,13 @@ interface ApiConfigResponse {
|
|
|
1079
1085
|
*/
|
|
1080
1086
|
batchExecutor?: Address;
|
|
1081
1087
|
/**
|
|
1082
|
-
*
|
|
1083
|
-
* PT→USDT swap fee) was deleted in the 2026-05-07 redeploy — fee
|
|
1084
|
-
* logic moved to `MintFeeWrapper` on the mint path, and v1.6 pools
|
|
1085
|
-
* use `hooks = address(0)`. Field retained for ABI back-compat
|
|
1086
|
-
* with v1.5 callers; `getContractAddresses(chainId)` returns a
|
|
1087
|
-
* dead sentinel.
|
|
1088
|
-
*/
|
|
1089
|
-
pafiHook?: Address;
|
|
1090
|
-
/**
|
|
1091
|
-
* v1.6 — single global MintFeeWrapper that skims a fee on every
|
|
1088
|
+
* Single global MintFeeWrapper that skims a fee on every
|
|
1092
1089
|
* sig-gated mint and distributes across the configured recipients.
|
|
1093
1090
|
*/
|
|
1094
1091
|
mintFeeWrapper?: Address;
|
|
1095
1092
|
};
|
|
1096
1093
|
/**
|
|
1097
|
-
*
|
|
1094
|
+
* Per-PointToken mint fee (in basis points, 0–10000) read from
|
|
1098
1095
|
* `MintFeeWrapper.totalFeeBps(pointToken)`. Frontend uses this to show
|
|
1099
1096
|
* "you'll receive X PT (Y% mint fee)" before user signs.
|
|
1100
1097
|
*
|
|
@@ -1169,10 +1166,8 @@ interface ApiUserResponse {
|
|
|
1169
1166
|
*/
|
|
1170
1167
|
totalBalance: bigint;
|
|
1171
1168
|
/**
|
|
1172
|
-
* @deprecated Use `offChainBalance` instead.
|
|
1173
|
-
*
|
|
1174
|
-
* mobile clients still read it. Will be removed in the next major
|
|
1175
|
-
* bump (v1.0).
|
|
1169
|
+
* @deprecated Use `offChainBalance` instead. Retained as a wire-level
|
|
1170
|
+
* alias for older mobile clients that still read it.
|
|
1176
1171
|
*/
|
|
1177
1172
|
balance: bigint;
|
|
1178
1173
|
isMinter: boolean;
|
|
@@ -1356,10 +1351,10 @@ interface IssuerApiHandlersConfig {
|
|
|
1356
1351
|
*/
|
|
1357
1352
|
pafiWebUrl?: string;
|
|
1358
1353
|
/**
|
|
1359
|
-
*
|
|
1360
|
-
*
|
|
1361
|
-
*
|
|
1362
|
-
*
|
|
1354
|
+
* MintFeeWrapper address used to read per-PointToken fee basis
|
|
1355
|
+
* points for `/config`. When omitted, the response will not include
|
|
1356
|
+
* `mintFeeBpsByToken` and FE must assume zero fee. Wrapper is shared
|
|
1357
|
+
* across PointTokens; per-token recipients live inside it.
|
|
1363
1358
|
*/
|
|
1364
1359
|
mintFeeWrapperAddress?: Address;
|
|
1365
1360
|
/** Required by `handleGasFee`; omit to disable the endpoint. */
|
|
@@ -1388,7 +1383,7 @@ interface IssuerApiHandlersConfig {
|
|
|
1388
1383
|
*
|
|
1389
1384
|
* Every protected handler takes a pre-verified `userAddress` as its first
|
|
1390
1385
|
* argument. The issuer's middleware wraps `authenticateRequest()` from
|
|
1391
|
-
* `@pafi/issuer` to extract that address from the Bearer token before
|
|
1386
|
+
* `@pafi-dev/issuer` to extract that address from the Bearer token before
|
|
1392
1387
|
* routing.
|
|
1393
1388
|
*/
|
|
1394
1389
|
declare class IssuerApiHandlers {
|
|
@@ -1462,9 +1457,8 @@ declare class IssuerApiHandlers {
|
|
|
1462
1457
|
/**
|
|
1463
1458
|
* `GET /user?chainId=<id>&user=<addr>&pointToken=<addr>`
|
|
1464
1459
|
*
|
|
1465
|
-
* Returns per-user state the frontend needs to build a fresh
|
|
1466
|
-
*
|
|
1467
|
-
* balance.
|
|
1460
|
+
* Returns per-user state the frontend needs to build a fresh mint:
|
|
1461
|
+
* on-chain nonces + minter status + off-chain balance.
|
|
1468
1462
|
*/
|
|
1469
1463
|
handleUser(userAddress: Address, request: ApiUserRequest): Promise<ApiUserResponse>;
|
|
1470
1464
|
/**
|
|
@@ -1490,7 +1484,7 @@ declare class IssuerApiHandlers {
|
|
|
1490
1484
|
}
|
|
1491
1485
|
|
|
1492
1486
|
/**
|
|
1493
|
-
*
|
|
1487
|
+
* Reverse flow — user-initiated PT redeem.
|
|
1494
1488
|
*
|
|
1495
1489
|
* User has on-chain PT, wants to convert back to off-chain points. The
|
|
1496
1490
|
* issuer backend signs a `BurnRequest` with its burner signer, reserves
|
|
@@ -2045,7 +2039,13 @@ declare function serializeUserOpTypedData(td: UserOpTypedData): SerializedUserOp
|
|
|
2045
2039
|
* (without re-estimated gas) don't accidentally zero out the original
|
|
2046
2040
|
* estimates.
|
|
2047
2041
|
*/
|
|
2048
|
-
|
|
2042
|
+
/**
|
|
2043
|
+
* Subset of `SponsorshipResponse` consumed by the merge/hash helpers.
|
|
2044
|
+
* Inlined as a structural type (rather than importing
|
|
2045
|
+
* `SponsorshipResponse` from `pafi-backend/client`) to keep
|
|
2046
|
+
* `userop-store` independent of the HTTP-client module.
|
|
2047
|
+
*/
|
|
2048
|
+
interface PaymasterGasEstimates {
|
|
2049
2049
|
paymaster: Address;
|
|
2050
2050
|
paymasterData: Hex;
|
|
2051
2051
|
paymasterVerificationGasLimit: bigint;
|
|
@@ -2055,7 +2055,8 @@ declare function mergePaymasterFields<T extends object>(userOp: T, paymasterFiel
|
|
|
2055
2055
|
preVerificationGas?: bigint;
|
|
2056
2056
|
maxFeePerGas?: bigint;
|
|
2057
2057
|
maxPriorityFeePerGas?: bigint;
|
|
2058
|
-
}
|
|
2058
|
+
}
|
|
2059
|
+
declare function mergePaymasterFields<T extends object>(userOp: T, paymasterFields: PaymasterGasEstimates | undefined): T;
|
|
2059
2060
|
interface PreparedUserOp {
|
|
2060
2061
|
/** The bundler-ready UserOp (with paymaster + Pimlico-quoted gas). */
|
|
2061
2062
|
userOp: PartialUserOperation & {
|
|
@@ -2071,6 +2072,51 @@ interface PreparedUserOp {
|
|
|
2071
2072
|
/** Typed-data payload — pass directly to `eth_signTypedData_v4`. */
|
|
2072
2073
|
typedData: SerializedUserOpTypedData;
|
|
2073
2074
|
}
|
|
2075
|
+
/**
|
|
2076
|
+
* Atomic "merge paymaster fields + compute hash + build typed data" —
|
|
2077
|
+
* the only place the SDK should be doing all three operations.
|
|
2078
|
+
*
|
|
2079
|
+
* Why bundled into one call:
|
|
2080
|
+
*
|
|
2081
|
+
* Pimlico's `pm_sponsorUserOperation` re-estimates
|
|
2082
|
+
* `callGasLimit` / `verificationGasLimit` / `preVerificationGas` and
|
|
2083
|
+
* the bundler fee fields (`maxFeePerGas` / `maxPriorityFeePerGas`),
|
|
2084
|
+
* then signs `paymasterData` over the new values. The EntryPoint
|
|
2085
|
+
* hashes the actual on-chain field values during validation, so
|
|
2086
|
+
* callers MUST overwrite the matching userOp fields BEFORE
|
|
2087
|
+
* computing the userOpHash. Forgetting any field triggers AA34
|
|
2088
|
+
* (paymaster signature mismatch) and/or AA24 (sender signature
|
|
2089
|
+
* mismatch) — opaque failures that take hours to debug.
|
|
2090
|
+
*
|
|
2091
|
+
* Splitting "merge" and "hash" into two free functions invited
|
|
2092
|
+
* exactly this bug — each call site reinvented the merge logic,
|
|
2093
|
+
* and one was already drifting (see audit M-02). Returning all
|
|
2094
|
+
* three pieces (`userOp`, `userOpHash`, `typedData`) from a single
|
|
2095
|
+
* call makes "hash before merge" structurally impossible: there is
|
|
2096
|
+
* no intermediate userOp to compute a stale hash over.
|
|
2097
|
+
*
|
|
2098
|
+
* Behaviour:
|
|
2099
|
+
* - When `paymasterFields` is undefined (paymaster declined / Path
|
|
2100
|
+
* C self-pay), the result is just the hash + typed-data of the
|
|
2101
|
+
* caller's `partialUserOp` — no fields are touched.
|
|
2102
|
+
* - When provided, only defined keys in `paymasterFields` overwrite
|
|
2103
|
+
* the matching fields. Original gas/fee estimates survive when
|
|
2104
|
+
* the paymaster did not re-estimate.
|
|
2105
|
+
*
|
|
2106
|
+
* Replaces:
|
|
2107
|
+
* - manual spread merges (e.g. previous `delegateHandler.ts`)
|
|
2108
|
+
* - `mergePaymasterFields` + separate `computeUserOpHash` +
|
|
2109
|
+
* `buildUserOpTypedData` triplets in any new call site.
|
|
2110
|
+
*
|
|
2111
|
+
* Note: the original `mergePaymasterFields` and the raw
|
|
2112
|
+
* `computeUserOpHash` / `buildUserOpTypedData` exports remain
|
|
2113
|
+
* available — use this helper unless you have a specific reason to
|
|
2114
|
+
* stage the operations.
|
|
2115
|
+
*/
|
|
2116
|
+
declare function applyPaymasterGasEstimates(partialUserOp: PartialUserOperation & {
|
|
2117
|
+
maxFeePerGas: bigint;
|
|
2118
|
+
maxPriorityFeePerGas: bigint;
|
|
2119
|
+
}, paymasterFields: PaymasterGasEstimates | undefined, chainId: number): PreparedUserOp;
|
|
2074
2120
|
interface PrepareMobileUserOpParams {
|
|
2075
2121
|
/** Lock id (issuer-generated) keying both store entry + ledger row. */
|
|
2076
2122
|
lockId: string;
|
|
@@ -2284,7 +2330,7 @@ interface IssuerStateValidatorLike {
|
|
|
2284
2330
|
preValidateMint(pointToken: Address, amount: bigint): Promise<unknown>;
|
|
2285
2331
|
}
|
|
2286
2332
|
/**
|
|
2287
|
-
*
|
|
2333
|
+
* Sig-gated mint handler — mirrors `PTRedeemHandler` on the mint side.
|
|
2288
2334
|
*
|
|
2289
2335
|
* Pre-validates against IssuerRegistry + on-chain totalSupply, locks the
|
|
2290
2336
|
* off-chain balance, builds the sponsored UserOp (mint + PT fee
|
|
@@ -2324,7 +2370,7 @@ interface PTClaimHandlerConfig {
|
|
|
2324
2370
|
signatureDeadlineSeconds?: number;
|
|
2325
2371
|
now?: () => number;
|
|
2326
2372
|
/**
|
|
2327
|
-
* Optional override for the
|
|
2373
|
+
* Optional override for the MintFeeWrapper address. By default the
|
|
2328
2374
|
* handler auto-resolves the wrapper from the request's `chainId` via
|
|
2329
2375
|
* `getContractAddresses(chainId).mintFeeWrapper`. Set this only when:
|
|
2330
2376
|
* - testing against a non-canonical wrapper deploy, or
|
|
@@ -2565,12 +2611,12 @@ declare function createSdkErrorMapper(factories: SdkErrorMapperFactories): (err:
|
|
|
2565
2611
|
/**
|
|
2566
2612
|
* Top-level configuration for `createIssuerService`.
|
|
2567
2613
|
*
|
|
2568
|
-
*
|
|
2614
|
+
* The SDK is HTTP-client-free: it signs EIP-712 messages, reads
|
|
2569
2615
|
* on-chain state, builds unsigned UserOperations, and maintains the
|
|
2570
2616
|
* off-chain ledger. It never broadcasts transactions — that's the
|
|
2571
2617
|
* frontend's responsibility via Bundler + Paymaster.
|
|
2572
2618
|
*
|
|
2573
|
-
* **Multi-token
|
|
2619
|
+
* **Multi-token:** Pass `pointTokenAddresses: Address[]` to
|
|
2574
2620
|
* support multiple PointTokens under a single issuer backend. Legacy
|
|
2575
2621
|
* `pointTokenAddress: Address` still works for single-token deployments.
|
|
2576
2622
|
* When both are provided, `pointTokenAddresses` takes precedence.
|
|
@@ -2584,8 +2630,8 @@ interface IssuerServiceConfig {
|
|
|
2584
2630
|
/**
|
|
2585
2631
|
* Issuer-specific contract addresses merged into the `/config` response.
|
|
2586
2632
|
* PAFI-owned addresses (batchExecutor, usdt, issuerRegistry, mintingOracle,
|
|
2587
|
-
*
|
|
2588
|
-
* can be omitted. Only `pointToken` / `pointTokens` must be provided.
|
|
2633
|
+
* mintFeeWrapper, …) are auto-resolved from `getContractAddresses(chainId)`
|
|
2634
|
+
* and can be omitted. Only `pointToken` / `pointTokens` must be provided.
|
|
2589
2635
|
*/
|
|
2590
2636
|
contracts?: Pick<ApiConfigResponse["contracts"], "pointToken" | "pointTokens" | "relay">;
|
|
2591
2637
|
/**
|
|
@@ -2637,11 +2683,11 @@ interface IssuerServiceConfig {
|
|
|
2637
2683
|
*/
|
|
2638
2684
|
autoStart?: boolean;
|
|
2639
2685
|
/**
|
|
2640
|
-
*
|
|
2641
|
-
*
|
|
2686
|
+
* Override the MintFeeWrapper address used by the indexer. When
|
|
2687
|
+
* omitted, the factory auto-resolves from
|
|
2642
2688
|
* `getContractAddresses(chainId).mintFeeWrapper`. Pass the
|
|
2643
2689
|
* dead-zero address (`0x...dEaD`) to force direct-Transfer mode
|
|
2644
|
-
* (
|
|
2690
|
+
* (useful for local fork tests).
|
|
2645
2691
|
*/
|
|
2646
2692
|
mintFeeWrapperAddress?: Address;
|
|
2647
2693
|
};
|
|
@@ -2681,11 +2727,6 @@ interface IssuerService {
|
|
|
2681
2727
|
fee: FeeManager | undefined;
|
|
2682
2728
|
/** All indexers keyed by PointToken address. */
|
|
2683
2729
|
indexers: Map<Address, PointIndexer>;
|
|
2684
|
-
/**
|
|
2685
|
-
* First indexer. Kept for backward compat with 0.1.x callers.
|
|
2686
|
-
* @deprecated use `indexers.get(tokenAddress)` for multi-token.
|
|
2687
|
-
*/
|
|
2688
|
-
indexer: PointIndexer;
|
|
2689
2730
|
/** Framework-agnostic HTTP handlers — wire into Express / Fastify / Hono. */
|
|
2690
2731
|
api: IssuerApiHandlers;
|
|
2691
2732
|
/**
|
|
@@ -2993,12 +3034,22 @@ interface SubgraphPoolsProviderConfig {
|
|
|
2993
3034
|
* Optional clock override for tests.
|
|
2994
3035
|
*/
|
|
2995
3036
|
now?: () => number;
|
|
3037
|
+
/**
|
|
3038
|
+
* Optional error callback. Invoked on every recoverable error (subgraph
|
|
3039
|
+
* unreachable, non-200 response, GraphQL errors, invalid pool payload).
|
|
3040
|
+
* The provider continues to return `{ pools: [] }` on error and also
|
|
3041
|
+
* logs via `console.warn`/`console.error`; this hook lets host apps
|
|
3042
|
+
* forward errors to their own observability stack without parsing logs.
|
|
3043
|
+
* Throwing inside this callback is swallowed so the provider remains
|
|
3044
|
+
* total. (Addresses CODE_REVIEW issuer MEDIUM-5.)
|
|
3045
|
+
*/
|
|
3046
|
+
onError?: (error: Error) => void;
|
|
2996
3047
|
}
|
|
2997
3048
|
/**
|
|
2998
3049
|
* Create a `PoolsProvider` backed by the PAFI subgraph.
|
|
2999
3050
|
*
|
|
3000
3051
|
* Queries the `pafiTokens` entity for the given `pointTokenAddress`,
|
|
3001
|
-
* reads its linked `Pool`, and returns a single-element `PoolKey[]`.
|
|
3052
|
+
* reads its linked V3 `Pool`, and returns a single-element `PoolKey[]`.
|
|
3002
3053
|
* Multiple pools per token would require a subgraph schema change.
|
|
3003
3054
|
*
|
|
3004
3055
|
* The result is cached in-process with a short TTL (default 30s). Pool
|
|
@@ -3009,19 +3060,22 @@ interface SubgraphPoolsProviderConfig {
|
|
|
3009
3060
|
* - the token is not registered on PAFI yet (no PafiToken entity)
|
|
3010
3061
|
* - the token is registered but its pool has not been initialised
|
|
3011
3062
|
* - the subgraph is unreachable or returns an error (logs to console,
|
|
3012
|
-
* does not throw — callers should
|
|
3063
|
+
* invokes `onError` if provided; does not throw — callers should
|
|
3064
|
+
* handle empty pool list gracefully)
|
|
3013
3065
|
*
|
|
3014
|
-
* Assumes the PAFI subgraph schema
|
|
3066
|
+
* Assumes the PAFI subgraph schema (`pafiToken { pool { id feeTier
|
|
3067
|
+
* token0 { id } token1 { id } } }`). Issuers with a custom subgraph must
|
|
3015
3068
|
* implement `PoolsProvider` themselves instead of using this helper.
|
|
3016
3069
|
*
|
|
3017
3070
|
* @example
|
|
3018
3071
|
* ```ts
|
|
3019
|
-
* import { createSubgraphPoolsProvider, createIssuerService } from "@pafi/issuer";
|
|
3072
|
+
* import { createSubgraphPoolsProvider, createIssuerService } from "@pafi-dev/issuer";
|
|
3020
3073
|
*
|
|
3021
3074
|
* const service = createIssuerService({
|
|
3022
3075
|
* // ...other config
|
|
3023
3076
|
* poolsProvider: createSubgraphPoolsProvider({
|
|
3024
3077
|
* subgraphUrl: "https://graph.pacificfinance.org/subgraphs/name/pafi",
|
|
3078
|
+
* onError: (err) => metrics.increment("issuer.pools.error", { reason: err.message }),
|
|
3025
3079
|
* }),
|
|
3026
3080
|
* });
|
|
3027
3081
|
* ```
|
|
@@ -3072,8 +3126,8 @@ interface SubgraphNativeUsdtQuoterConfig {
|
|
|
3072
3126
|
* Create a native→USDT quoter backed by the PAFI subgraph's
|
|
3073
3127
|
* `Bundle.ethPriceUSD`. The returned function has the shape
|
|
3074
3128
|
* `(amountNative: bigint) => Promise<bigint>` and can be passed as
|
|
3075
|
-
* `quoteNativeToFee` to `FeeManager` —
|
|
3076
|
-
*
|
|
3129
|
+
* `quoteNativeToFee` to `FeeManager` — the fee currency is configured
|
|
3130
|
+
* at the integration layer, not hardcoded here.
|
|
3077
3131
|
*
|
|
3078
3132
|
* Used by `FeeManager.estimateGasFee()` to convert the gas cost into
|
|
3079
3133
|
* an ERC-20 amount charged as part of the sponsored UserOp batch.
|
|
@@ -3142,50 +3196,6 @@ interface NativePtQuoterConfig {
|
|
|
3142
3196
|
*/
|
|
3143
3197
|
declare function createNativePtQuoter(config: NativePtQuoterConfig): (amountNative: bigint) => Promise<bigint>;
|
|
3144
3198
|
|
|
3145
|
-
/**
|
|
3146
|
-
* Combined off-chain + on-chain balance for a single user / token pair.
|
|
3147
|
-
*
|
|
3148
|
-
* - `offChain` — the issuer's ledger balance (available, excluding locks)
|
|
3149
|
-
* - `onChain` — the user's ERC-20 balance from `PointToken.balanceOf`
|
|
3150
|
-
* - `total` — `offChain + onChain` (what the Issuer App displays)
|
|
3151
|
-
*/
|
|
3152
|
-
interface CombinedBalance {
|
|
3153
|
-
offChain: bigint;
|
|
3154
|
-
onChain: bigint;
|
|
3155
|
-
total: bigint;
|
|
3156
|
-
}
|
|
3157
|
-
interface BalanceAggregatorConfig {
|
|
3158
|
-
provider: PublicClient;
|
|
3159
|
-
ledger: IPointLedger;
|
|
3160
|
-
}
|
|
3161
|
-
/**
|
|
3162
|
-
* v1.4 utility — aggregates off-chain + on-chain point balances into a
|
|
3163
|
-
* single view for the "combined balance" UI in the Issuer App.
|
|
3164
|
-
*
|
|
3165
|
-
* The `/user` API handler uses this internally; the helper is exposed
|
|
3166
|
-
* publicly so Issuer Apps can call it directly without going through
|
|
3167
|
-
* the HTTP layer (e.g., for server-rendered pages or admin dashboards).
|
|
3168
|
-
*
|
|
3169
|
-
* See [REQUIREMENTS_V2.md] §1 — "The Issuer App displays a combined
|
|
3170
|
-
* balance (off-chain points + on-chain PT) and does not surface USDT."
|
|
3171
|
-
*/
|
|
3172
|
-
declare class BalanceAggregator {
|
|
3173
|
-
private readonly provider;
|
|
3174
|
-
private readonly ledger;
|
|
3175
|
-
constructor(config: BalanceAggregatorConfig);
|
|
3176
|
-
/**
|
|
3177
|
-
* Combined balance for a single (user, token) pair. Fetches off-chain
|
|
3178
|
-
* + on-chain in parallel.
|
|
3179
|
-
*/
|
|
3180
|
-
getCombinedBalance(user: Address, pointToken: Address): Promise<CombinedBalance>;
|
|
3181
|
-
/**
|
|
3182
|
-
* Combined balance for multiple tokens owned by the same user. Runs
|
|
3183
|
-
* all lookups in parallel. Returns a Map keyed by the token address
|
|
3184
|
-
* (same casing as supplied — caller should normalize if needed).
|
|
3185
|
-
*/
|
|
3186
|
-
getCombinedBalanceMulti(user: Address, pointTokens: Address[]): Promise<Map<Address, CombinedBalance>>;
|
|
3187
|
-
}
|
|
3188
|
-
|
|
3189
3199
|
/**
|
|
3190
3200
|
* Typed errors thrown by the helpers below — issuer controllers map
|
|
3191
3201
|
* these to the appropriate HTTP status. We don't depend on @nestjs/common
|
|
@@ -3306,9 +3316,9 @@ interface IssuerRegistryRecord {
|
|
|
3306
3316
|
mintingOracle: Address;
|
|
3307
3317
|
}
|
|
3308
3318
|
/**
|
|
3309
|
-
*
|
|
3310
|
-
*
|
|
3311
|
-
* PointTokens with different supply policies.
|
|
3319
|
+
* Per-token cap config read from `MintingOracle.tokenCaps()`. Caps
|
|
3320
|
+
* live per PointToken (not per issuer), so a single issuer can run
|
|
3321
|
+
* many PointTokens with different supply policies.
|
|
3312
3322
|
*/
|
|
3313
3323
|
interface TokenCapRecord {
|
|
3314
3324
|
declaredTotalSupply: bigint;
|
|
@@ -3477,4 +3487,4 @@ declare class MemoryRedemptionHistoryStore implements IRedemptionHistoryStore {
|
|
|
3477
3487
|
|
|
3478
3488
|
declare const PAFI_ISSUER_SDK_VERSION: string;
|
|
3479
3489
|
|
|
3480
|
-
export { AdapterMisconfiguredError, type ApiConfigResponse, type ApiGasFeeResponse, type ApiLoginRequest, type ApiLoginResponse, type ApiNonceResponse, type ApiPoolsRequest, type ApiPoolsResponse, type ApiRedemptionEvaluateRequest, type ApiRedemptionEvaluateResponse, type ApiRedemptionPreviewRequest, type ApiRedemptionPreviewResponse, type ApiUserRequest, type ApiUserResponse, type AuthContext, AuthError, type AuthErrorCode, AuthService, type AuthServiceConfig,
|
|
3490
|
+
export { AdapterMisconfiguredError, type ApiConfigResponse, type ApiGasFeeResponse, type ApiLoginRequest, type ApiLoginResponse, type ApiNonceResponse, type ApiPoolsRequest, type ApiPoolsResponse, type ApiRedemptionEvaluateRequest, type ApiRedemptionEvaluateResponse, type ApiRedemptionPreviewRequest, type ApiRedemptionPreviewResponse, type ApiUserRequest, type ApiUserResponse, type AuthContext, AuthError, type AuthErrorCode, AuthService, type AuthServiceConfig, BundlerNotConfiguredError, BundlerRejectedError, type BurnEvent, BurnIndexer, type BurnIndexerConfig, type BurnStatusParams, type BurnStatusResponse, type ClaimDto, type ConfigDto, ConfigurationError, DEFAULT_REDEMPTION_POLICY, type DecodedCallDto, DefaultPolicyEngine, type DefaultPolicyEngineOptions, type DelegatePrepareDto, type DelegateStatusDto, type EvaluateInput, FeeManager, type FeeManagerConfig, type FetchFailureReason, type FetchResult, type GasFeeDto, type HandleDelegateSubmitParams, type HandleDelegateSubmitResult, type HandleMobilePrepareParams, type HandleMobilePrepareResult, type HandleMobileSubmitParams, type IIndexerCursorStore, type IPendingUserOpStore, type IPointLedger, type IPolicyEngine, type IRateLimiter, type IRedemptionHistoryStore, type ISessionStore, InMemoryCursorStore, IssuerApiAdapter, type IssuerApiAdapterConfig, IssuerApiHandlers, type IssuerApiHandlersConfig, type IssuerRegistryRecord, type IssuerService, type IssuerServiceConfig, IssuerStateError, IssuerStateValidator, LockNotFoundError, type LockedMintRequest, type LoginResult, MemoryPendingUserOpStore, MemoryRateLimiter, MemoryRedemptionHistoryStore, MemorySessionStore, type MemorySessionStoreOptions, type MintEvent, type MintStatusParams, type MintStatusResponse, type MintingStatus, type MobilePrepareDto, type MobileSubmitDto, type NativePtQuoterConfig, NonceManager, NoopRateLimiter, 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 PaymasterGasEstimates, type PendingCredit, type PendingUserOpEntry, PendingUserOpForbiddenError, PendingUserOpNotFoundError, type PerpDepositDto, PerpDepositError, PerpDepositHandler, type PerpDepositHandlerConfig, type PerpDepositRequest, type PerpDepositResponse, PointIndexer, type PointIndexerConfig, type PolicyDecision, type PolicyEvalRequest, PolicyProvider, type PolicyProviderConfig, type PoolsDto, type PoolsProvider, type PreValidateMintResult, type PrepareBurnParams, type PrepareMintParams, type PrepareMobileUserOpParams, type PrepareMobileUserOpResult, type PreparedUserOp, REDEMPTION_HISTORY_WINDOW_SEC, type RateLimitAction, type RateLimiterConfig, type RedeemDto, type RedeemPrepareDto, RedemptionService, type RedemptionServiceConfig, RelayError, type RelayErrorCode, RelayService, type RelayUserOpParams, type RelayUserOpRequest, type RelayUserOpResponse, type RequestPaymasterParams, type ResolvedPolicy, type RetryConfig, type SdkErrorBody, type SdkErrorMapperFactories, type SdkErrorStatus, type SerializedUserOpTypedData, type Session, SettlementClient, type SettlementClientConfig, type SponsorshipRequest, type SponsorshipResponse, type SponsorshipTarget, type SponsorshipUserOp, type SubgraphNativeUsdtQuoterConfig, type SubgraphPoolsProviderConfig, type UserDto, type UserHistory, applyPaymasterGasEstimates, authenticateRequest, buildSdkErrorBody, createIssuerService, createNativePtQuoter, createSdkErrorMapper, createSubgraphNativeUsdtQuoter, createSubgraphPoolsProvider, defaultPolicyFor, evaluateRedemption, handleClaimStatus, handleDelegateSubmit, handleMobilePrepare, handleMobileSubmit, handleRedeemStatus, mergePaymasterFields, prepareMobileUserOp, relayUserOp, requestPaymaster, serializeEntryToJsonRpc, serializeUserOpTypedData };
|