@pafi-dev/issuer 0.13.0 → 0.15.1
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 +109 -147
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +142 -132
- package/dist/index.d.ts +142 -132
- package/dist/index.js +100 -140
- package/dist/index.js.map +1 -1
- package/package.json +13 -11
package/README.md
CHANGED
|
@@ -14,40 +14,20 @@ interfaces. Don't bundle into a browser app — use
|
|
|
14
14
|
|
|
15
15
|
---
|
|
16
16
|
|
|
17
|
-
##
|
|
18
|
-
|
|
19
|
-
Tracks `@pafi-dev/core@0.10.0`. The `ReceiverConsent` mint path was
|
|
20
|
-
removed from the entire SDK chain because the deployed `PointToken`
|
|
21
|
-
contract never had it — what was conceptually a "sponsored mint" is
|
|
22
|
-
actually the path-2 `MintForRequest` sig-gated mint with sponsor-relayer
|
|
23
|
-
paying gas.
|
|
24
|
-
|
|
25
|
-
| Change | Detail |
|
|
26
|
-
|---|---|
|
|
27
|
-
| `ApiUserResponse.receiverConsentNonce` removed | The `/user` endpoint no longer returns this field. Callers using it for signing should call the path-2 mint flow with `mintRequestNonce` instead. |
|
|
28
|
-
| `UserDto.receiverConsentNonce` removed | Wire DTO drops the field — `IssuerApiAdapter.user()` response is one field smaller. |
|
|
29
|
-
| Action required for issuer backends | Bump `@pafi-dev/core` to `0.10.0`, remove any `receiverConsentNonce` field from your own DTOs / mobile API surface, drop FE code that signed `ReceiverConsent` typed data. |
|
|
30
|
-
|
|
31
|
-
### What's new in v1.6 / 0.12.x
|
|
32
|
-
|
|
33
|
-
| Change | Detail |
|
|
34
|
-
|---|---|
|
|
35
|
-
| `RelayService.prepareMint` branches direct vs wrapper | Auto-detects `MintFeeWrapper` from chainId. Direct: `pointToken.mint(...)`. Wrapper: `mintFeeWrapper.mintWithFee(...)` |
|
|
36
|
-
| `PTClaimHandler` auto-resolves wrapper | No env config needed — `getContractAddresses(chainId).mintFeeWrapper`. Override via `mintFeeWrapperAddress` for fork tests |
|
|
37
|
-
| `PointIndexer` wrapper mode | Listens to `MintFeeWrapper.MintWithFee(pointToken, to, gross, net, fee)` instead of `Transfer(0x0→user)` when wrapper is configured |
|
|
38
|
-
| `IssuerStateValidator` v1.6 struct | Reads 7-field Issuer struct + queries `MintingOracle.tokenCaps()` for caps |
|
|
39
|
-
| `/config` exposes `mintFeeBpsByToken` | FE can preview "you'll receive net = gross × (1-bps/10000)" before user signs |
|
|
40
|
-
| Operator fee fallback enabled by default | Mint not blocked when subgraph has no pool yet |
|
|
41
|
-
| `PafiBackendClient` error envelope fix | Reads nested `error.message` — exposes Pimlico AA codes instead of generic "HTTP 500" |
|
|
17
|
+
## v0.15.0 — Uniswap V3 migration (breaking)
|
|
42
18
|
|
|
43
|
-
|
|
19
|
+
- `createSubgraphPoolsProvider` now returns the V3 `PoolKey` shape (`{ token0, token1, fee }`) instead of the V4 shape (`{ currency0, currency1, fee, tickSpacing, hooks }`). Pulls through from `@pafi-dev/core`.
|
|
20
|
+
- New `onError?: (err: Error) => void` option — forward recoverable errors (network, GraphQL, parse) to your observability stack. Throws inside the callback are swallowed so the provider stays total.
|
|
21
|
+
- `feeTier` is range-checked (uint24, < 1_000_000) before building the `PoolKey`; invalid values are skipped with a console.error + `onError` invocation.
|
|
22
|
+
- Subgraph endpoint default → `…/pafi-subgraph-v4` (PAFI V3-fork DEX + extensions); see `@pafi-dev/core` for the constant.
|
|
23
|
+
- Bumps peer-deps on `@pafi-dev/core` to `^0.13.0` (V3 types + ABIs).
|
|
44
24
|
|
|
45
25
|
## Requirements
|
|
46
26
|
|
|
47
27
|
- Node.js ≥ 18
|
|
48
28
|
- TypeScript ≥ 5.0
|
|
49
29
|
- `viem` ^2.0.0 (peer)
|
|
50
|
-
- `@pafi-dev/core` (transitive — re-exported)
|
|
30
|
+
- `@pafi-dev/core` ^0.13.0 (transitive — re-exported)
|
|
51
31
|
|
|
52
32
|
## Installation
|
|
53
33
|
|
|
@@ -78,12 +58,11 @@ pnpm add @pafi-dev/issuer-postgres typeorm pg
|
|
|
78
58
|
├── userop-store — IPendingUserOpStore + MemoryPendingUserOpStore
|
|
79
59
|
├── pafi-backend — sponsor-relayer client + relay/paymaster helpers
|
|
80
60
|
├── auth — ISessionStore, AuthService (SIWE), MemorySessionStore
|
|
81
|
-
├── relay — RelayService (
|
|
61
|
+
├── relay — RelayService (wrapper-aware), FeeManager
|
|
82
62
|
├── pools — createSubgraphPoolsProvider, NativePtQuoter
|
|
83
63
|
├── policy — IPolicyEngine + DefaultPolicyEngine
|
|
84
|
-
├── balance — BalanceAggregator (off-chain + on-chain)
|
|
85
64
|
├── indexer — PointIndexer (wrapper + direct mode), BurnIndexer
|
|
86
|
-
├── issuer-state — IssuerStateValidator (
|
|
65
|
+
├── issuer-state — IssuerStateValidator (7-field struct + oracle.tokenCaps)
|
|
87
66
|
├── redemption — RedemptionService (per-issuer policy enforcement)
|
|
88
67
|
└── errors — PafiSdkError base class for typed errors
|
|
89
68
|
```
|
|
@@ -102,7 +81,7 @@ Controller ← thin: routing + DTO + auth context
|
|
|
102
81
|
IssuerApiAdapter ← orchestrates flows
|
|
103
82
|
↓
|
|
104
83
|
PTClaimHandler ← signs MintForRequest, locks balance, builds UserOp
|
|
105
|
-
(
|
|
84
|
+
(routes to wrapper.mintWithFee when wrapper configured)
|
|
106
85
|
PTRedeemHandler ← signs BurnRequest, reserves credit, builds UserOp
|
|
107
86
|
PerpDepositHandler ← Orderly Vault via PAFI Relay
|
|
108
87
|
↓
|
|
@@ -113,7 +92,7 @@ PafiBackendClient ← sponsor-relayer proxy
|
|
|
113
92
|
|
|
114
93
|
---
|
|
115
94
|
|
|
116
|
-
##
|
|
95
|
+
## Wrapper-mediated mint flow
|
|
117
96
|
|
|
118
97
|
```
|
|
119
98
|
[FE / mobile] → POST /claim/prepare
|
|
@@ -277,11 +256,11 @@ async function wrap<T>(fn: () => Promise<T>): Promise<T> {
|
|
|
277
256
|
| --- | --- | --- |
|
|
278
257
|
| `pools(authedAddr, chainId, pointToken)` | `GET /pools` | |
|
|
279
258
|
| `user(authedAddr, chainId, userAddr, pointToken)` | `GET /user` | |
|
|
280
|
-
| `config(chainId)` | `GET /config` |
|
|
259
|
+
| `config(chainId)` | `GET /config` | Includes `mintFeeBpsByToken` + `contracts.mintFeeWrapper` |
|
|
281
260
|
| `claim({ ...nonces })` | `POST /claim` (web — sync `calls[]`) | |
|
|
282
261
|
| `redeem({ amount, aaNonce, ... })` | `POST /redeem` | |
|
|
283
262
|
| `perpDeposit({ amount, brokerId, aaNonce, ... })` | `POST /perp-deposit` | |
|
|
284
|
-
| `claimPrepare(...)` / `claimSubmit(...)` | Mobile claim flow |
|
|
263
|
+
| `claimPrepare(...)` / `claimSubmit(...)` | Mobile claim flow | wrapper-aware |
|
|
285
264
|
| `redeemPrepare(...)` / `redeemSubmit(...)` | Mobile redeem flow | |
|
|
286
265
|
| `claimStatus(authedAddr, lockId)` / `redeemStatus(...)` | Status polling | |
|
|
287
266
|
| `delegateStatus(authedAddr, chainId)` | EIP-7702 — check delegation | |
|
|
@@ -358,7 +337,7 @@ const service = createIssuerService({
|
|
|
358
337
|
|
|
359
338
|
// Indexer listens to:
|
|
360
339
|
// - mode wrapper: MintFeeWrapper.MintWithFee filtered by pointToken
|
|
361
|
-
// (when wrapper is configured at chainId
|
|
340
|
+
// (when wrapper is configured at chainId)
|
|
362
341
|
// - mode direct: PointToken.Transfer(0x0 → user) (legacy / no wrapper)
|
|
363
342
|
```
|
|
364
343
|
|
|
@@ -387,29 +366,10 @@ All SDK errors inherit `PafiSdkError`. Subclasses + HTTP mapping:
|
|
|
387
366
|
|
|
388
367
|
---
|
|
389
368
|
|
|
390
|
-
## v1.5 → v1.6 migration checklist
|
|
391
|
-
|
|
392
|
-
1. `pnpm add @pafi-dev/issuer@latest @pafi-dev/core@latest` (≥ 0.12.7 + ≥ 0.9.6)
|
|
393
|
-
2. Update env: drop `MINT_FEE_WRAPPER_ADDRESS` if previously set
|
|
394
|
-
(SDK auto-resolves from chainId)
|
|
395
|
-
3. Re-deploy your issuer backend — `RelayService` now branches based on
|
|
396
|
-
wrapper presence; calldata changes from `mint(...)` to `mintWithFee(...)`
|
|
397
|
-
4. Verify on-chain prerequisites (PAFI ops responsibility):
|
|
398
|
-
- `IssuerRegistry.addIssuer(...)` cascade configures wrapper recipients
|
|
399
|
-
- `MintingOracle.registerToken(pointToken, issuer)` sets cap
|
|
400
|
-
- `PointToken.addMinter(signerAddress)` whitelists your signer
|
|
401
|
-
5. Indexer will pick up `MintWithFee` events automatically. If you wrote
|
|
402
|
-
custom Transfer-event consumers, switch to `MintWithFee`.
|
|
403
|
-
6. `/config` response now includes `mintFeeBpsByToken` — FE can preview
|
|
404
|
-
fee without round-tripping `getMintFeeBps()` separately.
|
|
405
|
-
|
|
406
|
-
---
|
|
407
|
-
|
|
408
369
|
## References
|
|
409
370
|
|
|
410
371
|
- Architecture: [`ARCHITECTURE.md`](../../ARCHITECTURE.md) at SDK root
|
|
411
372
|
- Fee flow & math: [`docs/FEE_FLOW.md`](../../../docs/FEE_FLOW.md)
|
|
412
|
-
- v1.6 SC commits: `cc26f62` (struct simplification), wrapper added
|
|
413
373
|
|
|
414
374
|
## License
|
|
415
375
|
|
package/dist/index.cjs
CHANGED
|
@@ -23,7 +23,6 @@ __export(index_exports, {
|
|
|
23
23
|
AdapterMisconfiguredError: () => AdapterMisconfiguredError,
|
|
24
24
|
AuthError: () => AuthError,
|
|
25
25
|
AuthService: () => AuthService,
|
|
26
|
-
BalanceAggregator: () => BalanceAggregator,
|
|
27
26
|
BundlerNotConfiguredError: () => BundlerNotConfiguredError,
|
|
28
27
|
BundlerRejectedError: () => BundlerRejectedError,
|
|
29
28
|
BurnIndexer: () => BurnIndexer,
|
|
@@ -65,6 +64,7 @@ __export(index_exports, {
|
|
|
65
64
|
SDK_ERROR_HTTP_STATUS_CODE: () => import_core.SDK_ERROR_HTTP_STATUS_CODE,
|
|
66
65
|
SettlementClient: () => SettlementClient,
|
|
67
66
|
ValidationError: () => import_core3.ValidationError,
|
|
67
|
+
applyPaymasterGasEstimates: () => applyPaymasterGasEstimates,
|
|
68
68
|
authenticateRequest: () => authenticateRequest,
|
|
69
69
|
buildErrorEnvelope: () => buildErrorEnvelope,
|
|
70
70
|
buildSdkErrorBody: () => buildSdkErrorBody,
|
|
@@ -945,7 +945,7 @@ var RelayService = class {
|
|
|
945
945
|
mintTarget = params.mintFeeWrapperAddress;
|
|
946
946
|
} else {
|
|
947
947
|
mintCallData = (0, import_viem3.encodeFunctionData)({
|
|
948
|
-
abi: import_core5.
|
|
948
|
+
abi: import_core5.POINT_TOKEN_ABI,
|
|
949
949
|
functionName: "mint",
|
|
950
950
|
args: [params.userAddress, params.amount, params.deadline, minterSig]
|
|
951
951
|
});
|
|
@@ -1010,8 +1010,8 @@ var RelayService = class {
|
|
|
1010
1010
|
* provides a pre-signed `BurnRequest` + sig bytes (typically from
|
|
1011
1011
|
* `PTRedeemHandler`).
|
|
1012
1012
|
*
|
|
1013
|
-
* Direct burn (no sig)
|
|
1014
|
-
*
|
|
1013
|
+
* Direct burn (no sig) is not used — every burn goes through the
|
|
1014
|
+
* issuer-signed `BurnRequest` path.
|
|
1015
1015
|
*/
|
|
1016
1016
|
async prepareBurn(params) {
|
|
1017
1017
|
if (!params.pointTokenAddress) {
|
|
@@ -1032,7 +1032,7 @@ var RelayService = class {
|
|
|
1032
1032
|
let burnCallData;
|
|
1033
1033
|
try {
|
|
1034
1034
|
burnCallData = (0, import_viem3.encodeFunctionData)({
|
|
1035
|
-
abi: import_core5.
|
|
1035
|
+
abi: import_core5.POINT_TOKEN_ABI,
|
|
1036
1036
|
functionName: "burn",
|
|
1037
1037
|
args: [
|
|
1038
1038
|
params.burnRequest.from,
|
|
@@ -1295,7 +1295,7 @@ var PointIndexer = class {
|
|
|
1295
1295
|
// Event fetching — two modes (wrapper vs direct)
|
|
1296
1296
|
// -------------------------------------------------------------------------
|
|
1297
1297
|
/**
|
|
1298
|
-
* Wrapper mode
|
|
1298
|
+
* Wrapper mode: listen for `MintWithFee` on the wrapper,
|
|
1299
1299
|
* filtered to events for THIS pointToken only. The event's `to` field
|
|
1300
1300
|
* is the actual end user, and `grossAmount` matches the lock amount.
|
|
1301
1301
|
*/
|
|
@@ -1817,9 +1817,8 @@ var IssuerApiHandlers = class _IssuerApiHandlers {
|
|
|
1817
1817
|
/**
|
|
1818
1818
|
* `GET /user?chainId=<id>&user=<addr>&pointToken=<addr>`
|
|
1819
1819
|
*
|
|
1820
|
-
* Returns per-user state the frontend needs to build a fresh
|
|
1821
|
-
*
|
|
1822
|
-
* balance.
|
|
1820
|
+
* Returns per-user state the frontend needs to build a fresh mint:
|
|
1821
|
+
* on-chain nonces + minter status + off-chain balance.
|
|
1823
1822
|
*/
|
|
1824
1823
|
async handleUser(userAddress, request) {
|
|
1825
1824
|
if (request.chainId !== this.chainId) {
|
|
@@ -2041,7 +2040,7 @@ var PTRedeemHandler = class {
|
|
|
2041
2040
|
try {
|
|
2042
2041
|
burnNonce = await this.provider.readContract({
|
|
2043
2042
|
address: this.pointTokenAddress,
|
|
2044
|
-
abi: import_core7.
|
|
2043
|
+
abi: import_core7.POINT_TOKEN_ABI,
|
|
2045
2044
|
functionName: "burnRequestNonces",
|
|
2046
2045
|
args: [request.userAddress]
|
|
2047
2046
|
});
|
|
@@ -2421,38 +2420,42 @@ function mergePaymasterFields(userOp, paymasterFields) {
|
|
|
2421
2420
|
}
|
|
2422
2421
|
return merged;
|
|
2423
2422
|
}
|
|
2424
|
-
|
|
2423
|
+
function applyPaymasterGasEstimates(partialUserOp, paymasterFields, chainId) {
|
|
2425
2424
|
const userOp = mergePaymasterFields(
|
|
2426
|
-
|
|
2427
|
-
|
|
2425
|
+
partialUserOp,
|
|
2426
|
+
paymasterFields
|
|
2428
2427
|
);
|
|
2429
|
-
|
|
2430
|
-
|
|
2431
|
-
(0, import_core9.
|
|
2428
|
+
return {
|
|
2429
|
+
userOp,
|
|
2430
|
+
userOpHash: (0, import_core9.computeUserOpHash)(userOp, chainId),
|
|
2431
|
+
typedData: serializeUserOpTypedData((0, import_core9.buildUserOpTypedData)(userOp, chainId))
|
|
2432
|
+
};
|
|
2433
|
+
}
|
|
2434
|
+
async function prepareMobileUserOp(params) {
|
|
2435
|
+
const sponsored = applyPaymasterGasEstimates(
|
|
2436
|
+
params.partialUserOp,
|
|
2437
|
+
params.paymasterFields,
|
|
2438
|
+
params.chainId
|
|
2432
2439
|
);
|
|
2440
|
+
const { userOp, userOpHash } = sponsored;
|
|
2433
2441
|
let fallback;
|
|
2434
2442
|
let fallbackEntry;
|
|
2435
2443
|
if (params.partialUserOpFallback) {
|
|
2436
|
-
|
|
2437
|
-
|
|
2438
|
-
|
|
2439
|
-
|
|
2440
|
-
|
|
2441
|
-
|
|
2442
|
-
|
|
2443
|
-
|
|
2444
|
+
fallback = applyPaymasterGasEstimates(
|
|
2445
|
+
{
|
|
2446
|
+
...params.partialUserOpFallback,
|
|
2447
|
+
maxFeePerGas: userOp.maxFeePerGas,
|
|
2448
|
+
maxPriorityFeePerGas: userOp.maxPriorityFeePerGas
|
|
2449
|
+
},
|
|
2450
|
+
void 0,
|
|
2451
|
+
params.chainId
|
|
2444
2452
|
);
|
|
2445
|
-
fallback = {
|
|
2446
|
-
userOp: fallbackUserOp,
|
|
2447
|
-
userOpHash: fallbackHash,
|
|
2448
|
-
typedData: fallbackTypedData
|
|
2449
|
-
};
|
|
2450
2453
|
fallbackEntry = {
|
|
2451
|
-
callData:
|
|
2452
|
-
callGasLimit:
|
|
2453
|
-
verificationGasLimit:
|
|
2454
|
-
preVerificationGas:
|
|
2455
|
-
userOpHash:
|
|
2454
|
+
callData: fallback.userOp.callData,
|
|
2455
|
+
callGasLimit: fallback.userOp.callGasLimit.toString(),
|
|
2456
|
+
verificationGasLimit: fallback.userOp.verificationGasLimit.toString(),
|
|
2457
|
+
preVerificationGas: fallback.userOp.preVerificationGas.toString(),
|
|
2458
|
+
userOpHash: fallback.userOpHash
|
|
2456
2459
|
};
|
|
2457
2460
|
}
|
|
2458
2461
|
const entry = {
|
|
@@ -2474,7 +2477,7 @@ async function prepareMobileUserOp(params) {
|
|
|
2474
2477
|
};
|
|
2475
2478
|
await params.store.save(params.lockId, entry, params.ttlSeconds);
|
|
2476
2479
|
return {
|
|
2477
|
-
sponsored
|
|
2480
|
+
sponsored,
|
|
2478
2481
|
fallback,
|
|
2479
2482
|
entry
|
|
2480
2483
|
};
|
|
@@ -3001,22 +3004,13 @@ async function handleDelegatePrepare(params) {
|
|
|
3001
3004
|
eip7702Auth: authorization,
|
|
3002
3005
|
onWarning: params.onWarning
|
|
3003
3006
|
});
|
|
3004
|
-
const
|
|
3005
|
-
|
|
3006
|
-
|
|
3007
|
-
|
|
3008
|
-
|
|
3009
|
-
|
|
3010
|
-
|
|
3011
|
-
maxFeePerGas: paymasterFields?.maxFeePerGas ?? userOp.maxFeePerGas,
|
|
3012
|
-
maxPriorityFeePerGas: paymasterFields?.maxPriorityFeePerGas ?? userOp.maxPriorityFeePerGas,
|
|
3013
|
-
paymaster: paymasterFields?.paymaster,
|
|
3014
|
-
paymasterVerificationGasLimit: paymasterFields?.paymasterVerificationGasLimit,
|
|
3015
|
-
paymasterPostOpGasLimit: paymasterFields?.paymasterPostOpGasLimit,
|
|
3016
|
-
paymasterData: paymasterFields?.paymasterData
|
|
3017
|
-
};
|
|
3018
|
-
const userOpHash = (0, import_core13.computeUserOpHash)(merged, params.chainId);
|
|
3019
|
-
const typed = (0, import_core13.buildUserOpTypedData)(merged, params.chainId);
|
|
3007
|
+
const prepared = applyPaymasterGasEstimates(
|
|
3008
|
+
userOp,
|
|
3009
|
+
paymasterFields,
|
|
3010
|
+
params.chainId
|
|
3011
|
+
);
|
|
3012
|
+
const merged = prepared.userOp;
|
|
3013
|
+
const userOpHash = prepared.userOpHash;
|
|
3020
3014
|
await params.store.save(
|
|
3021
3015
|
params.lockId,
|
|
3022
3016
|
{
|
|
@@ -3045,7 +3039,7 @@ async function handleDelegatePrepare(params) {
|
|
|
3045
3039
|
return {
|
|
3046
3040
|
lockId: params.lockId,
|
|
3047
3041
|
userOpHash,
|
|
3048
|
-
typedData:
|
|
3042
|
+
typedData: prepared.typedData,
|
|
3049
3043
|
expiresInSeconds: params.ttlSeconds,
|
|
3050
3044
|
isSponsored: !!paymasterFields
|
|
3051
3045
|
};
|
|
@@ -3499,6 +3493,7 @@ var IssuerApiAdapter = class {
|
|
|
3499
3493
|
var import_viem12 = require("viem");
|
|
3500
3494
|
var import_core15 = require("@pafi-dev/core");
|
|
3501
3495
|
var DEFAULT_CACHE_TTL_MS = 3e4;
|
|
3496
|
+
var MAX_REASONABLE_FEE_TIER = 1e6;
|
|
3502
3497
|
var POOL_QUERY = `
|
|
3503
3498
|
query GetPoolForPointToken($id: ID!) {
|
|
3504
3499
|
pafiToken(id: $id) {
|
|
@@ -3506,8 +3501,6 @@ var POOL_QUERY = `
|
|
|
3506
3501
|
pool {
|
|
3507
3502
|
id
|
|
3508
3503
|
feeTier
|
|
3509
|
-
tickSpacing
|
|
3510
|
-
hooks
|
|
3511
3504
|
token0 { id }
|
|
3512
3505
|
token1 { id }
|
|
3513
3506
|
}
|
|
@@ -3532,12 +3525,20 @@ function createSubgraphPoolsProvider(config = {}) {
|
|
|
3532
3525
|
const cacheTtl = config.cacheTtlMs ?? DEFAULT_CACHE_TTL_MS;
|
|
3533
3526
|
const fetchImpl = config.fetchImpl ?? globalThis.fetch;
|
|
3534
3527
|
const now = config.now ?? (() => Date.now());
|
|
3528
|
+
const onError = config.onError;
|
|
3535
3529
|
const cache = /* @__PURE__ */ new Map();
|
|
3536
3530
|
if (!fetchImpl) {
|
|
3537
3531
|
throw new Error(
|
|
3538
3532
|
"createSubgraphPoolsProvider: no fetch implementation available \u2014 pass `fetchImpl` or run on Node 18+"
|
|
3539
3533
|
);
|
|
3540
3534
|
}
|
|
3535
|
+
const reportError = (err) => {
|
|
3536
|
+
if (!onError) return;
|
|
3537
|
+
try {
|
|
3538
|
+
onError(err);
|
|
3539
|
+
} catch {
|
|
3540
|
+
}
|
|
3541
|
+
};
|
|
3541
3542
|
return async (request) => {
|
|
3542
3543
|
const cacheKey = `${request.chainId}:${request.pointTokenAddress.toLowerCase()}`;
|
|
3543
3544
|
if (cacheTtl > 0) {
|
|
@@ -3549,7 +3550,8 @@ function createSubgraphPoolsProvider(config = {}) {
|
|
|
3549
3550
|
const pools = await fetchPoolsFromSubgraph(
|
|
3550
3551
|
fetchImpl,
|
|
3551
3552
|
subgraphUrl,
|
|
3552
|
-
request.pointTokenAddress
|
|
3553
|
+
request.pointTokenAddress,
|
|
3554
|
+
reportError
|
|
3553
3555
|
);
|
|
3554
3556
|
if (cacheTtl > 0) {
|
|
3555
3557
|
cache.set(cacheKey, {
|
|
@@ -3560,7 +3562,7 @@ function createSubgraphPoolsProvider(config = {}) {
|
|
|
3560
3562
|
return { pools };
|
|
3561
3563
|
};
|
|
3562
3564
|
}
|
|
3563
|
-
async function fetchPoolsFromSubgraph(fetchImpl, subgraphUrl, pointTokenAddress) {
|
|
3565
|
+
async function fetchPoolsFromSubgraph(fetchImpl, subgraphUrl, pointTokenAddress, reportError) {
|
|
3564
3566
|
let response;
|
|
3565
3567
|
try {
|
|
3566
3568
|
response = await fetchImpl(subgraphUrl, {
|
|
@@ -3572,24 +3574,38 @@ async function fetchPoolsFromSubgraph(fetchImpl, subgraphUrl, pointTokenAddress)
|
|
|
3572
3574
|
})
|
|
3573
3575
|
});
|
|
3574
3576
|
} catch (err) {
|
|
3577
|
+
const error = err instanceof Error ? err : new Error(String(err));
|
|
3575
3578
|
console.warn(
|
|
3576
3579
|
"[subgraphPoolsProvider] subgraph unreachable:",
|
|
3577
|
-
|
|
3580
|
+
error.message
|
|
3578
3581
|
);
|
|
3582
|
+
reportError(error);
|
|
3579
3583
|
return [];
|
|
3580
3584
|
}
|
|
3581
3585
|
if (!response.ok) {
|
|
3582
|
-
|
|
3583
|
-
`
|
|
3586
|
+
const error = new Error(
|
|
3587
|
+
`subgraph returned HTTP ${response.status}`
|
|
3584
3588
|
);
|
|
3589
|
+
console.warn(`[subgraphPoolsProvider] ${error.message}`);
|
|
3590
|
+
reportError(error);
|
|
3585
3591
|
return [];
|
|
3586
3592
|
}
|
|
3587
|
-
|
|
3588
|
-
|
|
3593
|
+
let json;
|
|
3594
|
+
try {
|
|
3595
|
+
json = await response.json();
|
|
3596
|
+
} catch (err) {
|
|
3597
|
+
const error = err instanceof Error ? err : new Error(String(err));
|
|
3589
3598
|
console.warn(
|
|
3590
|
-
"[subgraphPoolsProvider] subgraph
|
|
3591
|
-
|
|
3599
|
+
"[subgraphPoolsProvider] subgraph returned non-JSON:",
|
|
3600
|
+
error.message
|
|
3592
3601
|
);
|
|
3602
|
+
reportError(error);
|
|
3603
|
+
return [];
|
|
3604
|
+
}
|
|
3605
|
+
if (json.errors && json.errors.length > 0) {
|
|
3606
|
+
const msg = json.errors.map((e) => e.message).join("; ");
|
|
3607
|
+
console.warn("[subgraphPoolsProvider] subgraph errors:", msg);
|
|
3608
|
+
reportError(new Error(`subgraph GraphQL errors: ${msg}`));
|
|
3593
3609
|
return [];
|
|
3594
3610
|
}
|
|
3595
3611
|
const token = json.data?.pafiToken;
|
|
@@ -3597,40 +3613,35 @@ async function fetchPoolsFromSubgraph(fetchImpl, subgraphUrl, pointTokenAddress)
|
|
|
3597
3613
|
return [];
|
|
3598
3614
|
}
|
|
3599
3615
|
const { pool } = token;
|
|
3600
|
-
if (!(0, import_viem12.isAddress)(pool.hooks)) {
|
|
3601
|
-
console.error(
|
|
3602
|
-
"[PAFI] SubgraphPoolsProvider: invalid hooks address in response:",
|
|
3603
|
-
pool.hooks,
|
|
3604
|
-
"\u2014 skipping pool"
|
|
3605
|
-
);
|
|
3606
|
-
return [];
|
|
3607
|
-
}
|
|
3608
3616
|
if (!(0, import_viem12.isAddress)(pool.token0.id) || !(0, import_viem12.isAddress)(pool.token1.id)) {
|
|
3609
|
-
|
|
3610
|
-
"[PAFI] SubgraphPoolsProvider: invalid token address in response
|
|
3617
|
+
const error = new Error(
|
|
3618
|
+
"[PAFI] SubgraphPoolsProvider: invalid token address in response"
|
|
3611
3619
|
);
|
|
3620
|
+
console.error(error.message, "\u2014 skipping pool");
|
|
3621
|
+
reportError(error);
|
|
3612
3622
|
return [];
|
|
3613
3623
|
}
|
|
3614
|
-
|
|
3615
|
-
|
|
3616
|
-
|
|
3624
|
+
const feeNum = Number(pool.feeTier);
|
|
3625
|
+
if (!Number.isInteger(feeNum) || feeNum < 0 || feeNum >= MAX_REASONABLE_FEE_TIER) {
|
|
3626
|
+
const error = new Error(
|
|
3627
|
+
`[PAFI] SubgraphPoolsProvider: invalid feeTier value: ${pool.feeTier}`
|
|
3617
3628
|
);
|
|
3629
|
+
console.error(error.message, "\u2014 skipping pool");
|
|
3630
|
+
reportError(error);
|
|
3618
3631
|
return [];
|
|
3619
3632
|
}
|
|
3620
|
-
const [
|
|
3633
|
+
const [token0, token1] = sortTokens(
|
|
3621
3634
|
pool.token0.id,
|
|
3622
3635
|
pool.token1.id
|
|
3623
3636
|
);
|
|
3624
3637
|
const poolKey = {
|
|
3625
|
-
|
|
3626
|
-
|
|
3627
|
-
fee:
|
|
3628
|
-
tickSpacing: Number(pool.tickSpacing),
|
|
3629
|
-
hooks: pool.hooks
|
|
3638
|
+
token0,
|
|
3639
|
+
token1,
|
|
3640
|
+
fee: feeNum
|
|
3630
3641
|
};
|
|
3631
3642
|
return [poolKey];
|
|
3632
3643
|
}
|
|
3633
|
-
function
|
|
3644
|
+
function sortTokens(a, b) {
|
|
3634
3645
|
return a.toLowerCase() < b.toLowerCase() ? [a, b] : [b, a];
|
|
3635
3646
|
}
|
|
3636
3647
|
|
|
@@ -3858,54 +3869,8 @@ function parseBigDecimalTo18(s) {
|
|
|
3858
3869
|
return BigInt(whole + padded);
|
|
3859
3870
|
}
|
|
3860
3871
|
|
|
3861
|
-
// src/balance/balanceAggregator.ts
|
|
3862
|
-
var import_core16 = require("@pafi-dev/core");
|
|
3863
|
-
var BalanceAggregator = class {
|
|
3864
|
-
provider;
|
|
3865
|
-
ledger;
|
|
3866
|
-
constructor(config) {
|
|
3867
|
-
if (!config.provider) {
|
|
3868
|
-
throw new Error("BalanceAggregator: provider is required");
|
|
3869
|
-
}
|
|
3870
|
-
if (!config.ledger) {
|
|
3871
|
-
throw new Error("BalanceAggregator: ledger is required");
|
|
3872
|
-
}
|
|
3873
|
-
this.provider = config.provider;
|
|
3874
|
-
this.ledger = config.ledger;
|
|
3875
|
-
}
|
|
3876
|
-
/**
|
|
3877
|
-
* Combined balance for a single (user, token) pair. Fetches off-chain
|
|
3878
|
-
* + on-chain in parallel.
|
|
3879
|
-
*/
|
|
3880
|
-
async getCombinedBalance(user, pointToken) {
|
|
3881
|
-
const [offChain, onChain] = await Promise.all([
|
|
3882
|
-
this.ledger.getBalance(user, pointToken),
|
|
3883
|
-
(0, import_core16.getPointTokenBalance)(this.provider, pointToken, user)
|
|
3884
|
-
]);
|
|
3885
|
-
return {
|
|
3886
|
-
offChain,
|
|
3887
|
-
onChain,
|
|
3888
|
-
total: offChain + onChain
|
|
3889
|
-
};
|
|
3890
|
-
}
|
|
3891
|
-
/**
|
|
3892
|
-
* Combined balance for multiple tokens owned by the same user. Runs
|
|
3893
|
-
* all lookups in parallel. Returns a Map keyed by the token address
|
|
3894
|
-
* (same casing as supplied — caller should normalize if needed).
|
|
3895
|
-
*/
|
|
3896
|
-
async getCombinedBalanceMulti(user, pointTokens) {
|
|
3897
|
-
const entries = await Promise.all(
|
|
3898
|
-
pointTokens.map(async (token) => {
|
|
3899
|
-
const balance = await this.getCombinedBalance(user, token);
|
|
3900
|
-
return [token, balance];
|
|
3901
|
-
})
|
|
3902
|
-
);
|
|
3903
|
-
return new Map(entries);
|
|
3904
|
-
}
|
|
3905
|
-
};
|
|
3906
|
-
|
|
3907
3872
|
// src/pafi-backend/client.ts
|
|
3908
|
-
var
|
|
3873
|
+
var import_core16 = require("@pafi-dev/core");
|
|
3909
3874
|
function extractPafiErrorFields(json, status) {
|
|
3910
3875
|
const inner = typeof json.error === "object" && json.error !== null ? json.error : null;
|
|
3911
3876
|
const code = inner?.code ?? json.code ?? "INTERNAL_ERROR";
|
|
@@ -3926,7 +3891,7 @@ var PafiBackendClient = class {
|
|
|
3926
3891
|
if (!config.issuerId) throw new Error("PafiBackendClient: issuerId is required");
|
|
3927
3892
|
if (!config.apiKey) throw new Error("PafiBackendClient: apiKey is required");
|
|
3928
3893
|
this.config = config;
|
|
3929
|
-
this.baseUrl = (0,
|
|
3894
|
+
this.baseUrl = (0, import_core16.getPafiServiceUrls)(config.chainId).sponsorRelayer;
|
|
3930
3895
|
}
|
|
3931
3896
|
async requestSponsorship(request) {
|
|
3932
3897
|
const maxAttempts = this.config.retry?.maxAttempts ?? 1;
|
|
@@ -4087,7 +4052,7 @@ var PafiBackendClient = class {
|
|
|
4087
4052
|
|
|
4088
4053
|
// src/config.ts
|
|
4089
4054
|
var import_viem14 = require("viem");
|
|
4090
|
-
var
|
|
4055
|
+
var import_core18 = require("@pafi-dev/core");
|
|
4091
4056
|
|
|
4092
4057
|
// src/redemption/evaluator.ts
|
|
4093
4058
|
var SECONDS_PER_DAY = 24 * 60 * 60;
|
|
@@ -4192,7 +4157,7 @@ function nextBlackoutEndAfter(windows, nowUnixSec) {
|
|
|
4192
4157
|
var REDEMPTION_HISTORY_WINDOW_SEC = SECONDS_PER_DAY;
|
|
4193
4158
|
|
|
4194
4159
|
// src/redemption/settlementClient.ts
|
|
4195
|
-
var
|
|
4160
|
+
var import_core17 = require("@pafi-dev/core");
|
|
4196
4161
|
var DEFAULT_TIMEOUT_MS = 1e3;
|
|
4197
4162
|
var SettlementClient = class {
|
|
4198
4163
|
config;
|
|
@@ -4201,7 +4166,7 @@ var SettlementClient = class {
|
|
|
4201
4166
|
if (!config.issuerId) throw new Error("SettlementClient: issuerId is required");
|
|
4202
4167
|
if (!config.apiKey) throw new Error("SettlementClient: apiKey is required");
|
|
4203
4168
|
this.config = {
|
|
4204
|
-
baseUrl: (0,
|
|
4169
|
+
baseUrl: (0, import_core17.getPafiServiceUrls)(config.chainId).issuerApi.replace(/\/+$/, ""),
|
|
4205
4170
|
issuerId: config.issuerId,
|
|
4206
4171
|
apiKey: config.apiKey,
|
|
4207
4172
|
fetchTimeoutMs: config.fetchTimeoutMs ?? DEFAULT_TIMEOUT_MS,
|
|
@@ -4438,7 +4403,7 @@ function createIssuerService(config) {
|
|
|
4438
4403
|
provider: config.provider
|
|
4439
4404
|
});
|
|
4440
4405
|
}
|
|
4441
|
-
const sdkWrapperAddress = (0,
|
|
4406
|
+
const sdkWrapperAddress = (0, import_core18.getContractAddresses)(config.chainId).mintFeeWrapper;
|
|
4442
4407
|
const wrapperOverride = config.indexer?.mintFeeWrapperAddress;
|
|
4443
4408
|
const resolvedWrapperAddress = wrapperOverride !== void 0 ? wrapperOverride : sdkWrapperAddress;
|
|
4444
4409
|
const indexers = /* @__PURE__ */ new Map();
|
|
@@ -4468,14 +4433,12 @@ function createIssuerService(config) {
|
|
|
4468
4433
|
}
|
|
4469
4434
|
indexers.set(tokenAddress, new PointIndexer(indexerConfig));
|
|
4470
4435
|
}
|
|
4471
|
-
const
|
|
4472
|
-
const chainAddresses = (0, import_core19.getContractAddresses)(config.chainId);
|
|
4436
|
+
const chainAddresses = (0, import_core18.getContractAddresses)(config.chainId);
|
|
4473
4437
|
const resolvedContracts = {
|
|
4474
4438
|
batchExecutor: chainAddresses.batchExecutor,
|
|
4475
4439
|
usdt: chainAddresses.usdt,
|
|
4476
4440
|
issuerRegistry: chainAddresses.issuerRegistry,
|
|
4477
4441
|
mintingOracle: chainAddresses.mintingOracle,
|
|
4478
|
-
pafiHook: chainAddresses.pafiHook,
|
|
4479
4442
|
...config.contracts
|
|
4480
4443
|
};
|
|
4481
4444
|
if (resolvedWrapperAddress !== void 0) {
|
|
@@ -4528,7 +4491,6 @@ function createIssuerService(config) {
|
|
|
4528
4491
|
relay: relayService,
|
|
4529
4492
|
fee: feeManager,
|
|
4530
4493
|
indexers,
|
|
4531
|
-
indexer: firstIndexer,
|
|
4532
4494
|
api: handlers,
|
|
4533
4495
|
redemption
|
|
4534
4496
|
};
|
|
@@ -4536,7 +4498,7 @@ function createIssuerService(config) {
|
|
|
4536
4498
|
|
|
4537
4499
|
// src/issuer-state/validator.ts
|
|
4538
4500
|
var import_viem15 = require("viem");
|
|
4539
|
-
var
|
|
4501
|
+
var import_core19 = require("@pafi-dev/core");
|
|
4540
4502
|
var ISSUER_RECORD_TTL_MS = 3e4;
|
|
4541
4503
|
var IssuerStateValidator = class _IssuerStateValidator {
|
|
4542
4504
|
constructor(provider, registryAddress) {
|
|
@@ -4553,7 +4515,7 @@ var IssuerStateValidator = class _IssuerStateValidator {
|
|
|
4553
4515
|
* `CONTRACT_ADDRESSES` map for the given chain.
|
|
4554
4516
|
*/
|
|
4555
4517
|
static forChain(provider, chainId) {
|
|
4556
|
-
const { issuerRegistry } = (0,
|
|
4518
|
+
const { issuerRegistry } = (0, import_core19.getContractAddresses)(chainId);
|
|
4557
4519
|
return new _IssuerStateValidator(provider, issuerRegistry);
|
|
4558
4520
|
}
|
|
4559
4521
|
/**
|
|
@@ -4582,7 +4544,7 @@ var IssuerStateValidator = class _IssuerStateValidator {
|
|
|
4582
4544
|
if (cached) return cached;
|
|
4583
4545
|
const issuer = await this.provider.readContract({
|
|
4584
4546
|
address: key,
|
|
4585
|
-
abi:
|
|
4547
|
+
abi: import_core19.POINT_TOKEN_ABI,
|
|
4586
4548
|
functionName: "issuer"
|
|
4587
4549
|
});
|
|
4588
4550
|
this.pointTokenIssuerCache.set(key, (0, import_viem15.getAddress)(issuer));
|
|
@@ -4662,7 +4624,7 @@ var IssuerStateValidator = class _IssuerStateValidator {
|
|
|
4662
4624
|
const issuerAddr = await this.getIssuerAddressForPointToken(tokenAddr);
|
|
4663
4625
|
const issuerStruct = await this.provider.readContract({
|
|
4664
4626
|
address: this.registryAddress,
|
|
4665
|
-
abi:
|
|
4627
|
+
abi: import_core19.issuerRegistryAbi,
|
|
4666
4628
|
functionName: "getIssuer",
|
|
4667
4629
|
args: [issuerAddr]
|
|
4668
4630
|
});
|
|
@@ -4676,10 +4638,10 @@ var IssuerStateValidator = class _IssuerStateValidator {
|
|
|
4676
4638
|
mintingOracle: issuerStruct.mintingOracle
|
|
4677
4639
|
};
|
|
4678
4640
|
const [tokenCap, totalSupply] = await Promise.all([
|
|
4679
|
-
(0,
|
|
4641
|
+
(0, import_core19.getTokenCap)(this.provider, issuer.mintingOracle, tokenAddr),
|
|
4680
4642
|
this.provider.readContract({
|
|
4681
4643
|
address: tokenAddr,
|
|
4682
|
-
abi:
|
|
4644
|
+
abi: import_core19.POINT_TOKEN_ABI,
|
|
4683
4645
|
functionName: "totalSupply"
|
|
4684
4646
|
})
|
|
4685
4647
|
]);
|
|
@@ -4736,13 +4698,12 @@ var MemoryRedemptionHistoryStore = class {
|
|
|
4736
4698
|
};
|
|
4737
4699
|
|
|
4738
4700
|
// src/index.ts
|
|
4739
|
-
var PAFI_ISSUER_SDK_VERSION = true ? "0.
|
|
4701
|
+
var PAFI_ISSUER_SDK_VERSION = true ? "0.15.1" : "dev";
|
|
4740
4702
|
// Annotate the CommonJS export names for ESM import in node:
|
|
4741
4703
|
0 && (module.exports = {
|
|
4742
4704
|
AdapterMisconfiguredError,
|
|
4743
4705
|
AuthError,
|
|
4744
4706
|
AuthService,
|
|
4745
|
-
BalanceAggregator,
|
|
4746
4707
|
BundlerNotConfiguredError,
|
|
4747
4708
|
BundlerRejectedError,
|
|
4748
4709
|
BurnIndexer,
|
|
@@ -4784,6 +4745,7 @@ var PAFI_ISSUER_SDK_VERSION = true ? "0.13.0" : "dev";
|
|
|
4784
4745
|
SDK_ERROR_HTTP_STATUS_CODE,
|
|
4785
4746
|
SettlementClient,
|
|
4786
4747
|
ValidationError,
|
|
4748
|
+
applyPaymasterGasEstimates,
|
|
4787
4749
|
authenticateRequest,
|
|
4788
4750
|
buildErrorEnvelope,
|
|
4789
4751
|
buildSdkErrorBody,
|