@pafi-dev/issuer 0.5.37 → 0.5.39

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.js CHANGED
@@ -1,3 +1,19 @@
1
+ // src/errors.ts
2
+ var PafiSdkError = class extends Error {
3
+ /**
4
+ * `true` when the FE should consider a retry safe — typically because
5
+ * the failure is transient (`MINT_CAP_EXCEEDED` may free up,
6
+ * `RELAY_FEE_EXCEEDS_AMOUNT` may drop on next quote). Defaults to
7
+ * `false` — subclasses opt in per-code.
8
+ */
9
+ safeToRetry = false;
10
+ details;
11
+ constructor(message) {
12
+ super(message);
13
+ this.name = new.target.name;
14
+ }
15
+ };
16
+
1
17
  // src/policy/defaultPolicy.ts
2
18
  var DefaultPolicyEngine = class {
3
19
  ledger;
@@ -1311,21 +1327,27 @@ var IssuerApiHandlers = class {
1311
1327
 
1312
1328
  // src/api/handlers/ptRedeemHandler.ts
1313
1329
  import { getAddress as getAddress6 } from "viem";
1314
- import { signBurnRequest, POINT_TOKEN_V2_ABI as POINT_TOKEN_V2_ABI2, getPointTokenBalance as getPointTokenBalance2 } from "@pafi-dev/core";
1330
+ import {
1331
+ signBurnRequest,
1332
+ POINT_TOKEN_V2_ABI as POINT_TOKEN_V2_ABI2,
1333
+ getPointTokenBalance as getPointTokenBalance2,
1334
+ getContractAddresses as getContractAddresses2
1335
+ } from "@pafi-dev/core";
1315
1336
  var DEFAULT_REDEEM_LOCK_MS = 15 * 60 * 1e3;
1316
1337
  var DEFAULT_SIG_DEADLINE_SEC = 15 * 60;
1317
- var PTRedeemError = class extends Error {
1338
+ var PTRedeemError = class extends PafiSdkError {
1339
+ httpStatus = "unprocessable";
1340
+ code;
1318
1341
  constructor(code, message) {
1319
1342
  super(message);
1320
1343
  this.code = code;
1321
- this.name = "PTRedeemError";
1322
1344
  }
1323
- code;
1324
1345
  };
1325
1346
  var PTRedeemHandler = class {
1326
1347
  ledger;
1327
1348
  relayService;
1328
1349
  provider;
1350
+ feeService;
1329
1351
  pointTokenAddress;
1330
1352
  batchExecutorAddress;
1331
1353
  chainId;
@@ -1364,6 +1386,7 @@ var PTRedeemHandler = class {
1364
1386
  this.ledger = config.ledger;
1365
1387
  this.relayService = config.relayService;
1366
1388
  this.provider = config.provider;
1389
+ this.feeService = config.feeService;
1367
1390
  this.pointTokenAddress = getAddress6(config.pointTokenAddress);
1368
1391
  this.batchExecutorAddress = getAddress6(config.batchExecutorAddress);
1369
1392
  this.chainId = config.chainId;
@@ -1421,7 +1444,15 @@ var PTRedeemHandler = class {
1421
1444
  }
1422
1445
  }
1423
1446
  async _handleAfterNonceLock(request, burnNonce) {
1424
- const fee = request.feeAmount && request.feeAmount > 0n ? request.feeAmount : 0n;
1447
+ let fee;
1448
+ if (request.feeAmount !== void 0) {
1449
+ fee = request.feeAmount > 0n ? request.feeAmount : 0n;
1450
+ } else if (this.feeService) {
1451
+ fee = await this.feeService.estimateGasFee();
1452
+ } else {
1453
+ fee = 0n;
1454
+ }
1455
+ const feeRecipient = request.feeRecipient ?? (request.chainId !== void 0 ? getContractAddresses2(request.chainId).pafiFeeRecipient : getContractAddresses2(this.chainId).pafiFeeRecipient);
1425
1456
  if (fee > 0n && fee >= request.amount) {
1426
1457
  throw new PTRedeemError(
1427
1458
  "INVALID_AMOUNT",
@@ -1478,7 +1509,7 @@ var PTRedeemHandler = class {
1478
1509
  burnRequest: sponsoredBurnRequest,
1479
1510
  burnerSignature: sponsoredSig,
1480
1511
  feeAmount: fee,
1481
- feeRecipient: request.feeRecipient
1512
+ feeRecipient
1482
1513
  });
1483
1514
  let fallback = void 0;
1484
1515
  if (fee > 0n) {
@@ -1527,6 +1558,7 @@ var PTRedeemHandler = class {
1527
1558
  lockId: sponsoredLockId,
1528
1559
  userOp: sponsoredUserOp,
1529
1560
  netCreditAmount: sponsoredBurnAmount,
1561
+ feeAmount: fee,
1530
1562
  fallback,
1531
1563
  expiresInSeconds: Math.floor(this.redeemLockDurationMs / 1e3),
1532
1564
  signatureDeadline: deadline
@@ -1599,11 +1631,11 @@ var TopUpRedemptionHandler = class {
1599
1631
  };
1600
1632
 
1601
1633
  // src/api/statusHandlers.ts
1602
- var LockNotFoundError = class extends Error {
1634
+ var LockNotFoundError = class extends PafiSdkError {
1603
1635
  code = "LOCK_NOT_FOUND";
1636
+ httpStatus = "not_found";
1604
1637
  constructor() {
1605
1638
  super("Lock not found or does not belong to authenticated user");
1606
- this.name = "LockNotFoundError";
1607
1639
  }
1608
1640
  };
1609
1641
  async function handleClaimStatus(params) {
@@ -1699,6 +1731,7 @@ async function handleRedeemStatus(params) {
1699
1731
  }
1700
1732
 
1701
1733
  // src/api/mobileHandlers.ts
1734
+ import { getAddress as getAddress8 } from "viem";
1702
1735
  import {
1703
1736
  ENTRY_POINT_V08,
1704
1737
  parseEip7702DelegatedAddress
@@ -1841,21 +1874,21 @@ async function prepareMobileUserOp(params) {
1841
1874
  }
1842
1875
 
1843
1876
  // src/pafi-backend/helpers.ts
1844
- var BundlerNotConfiguredError = class extends Error {
1877
+ var BundlerNotConfiguredError = class extends PafiSdkError {
1845
1878
  code = "BUNDLER_NOT_CONFIGURED";
1879
+ httpStatus = "service_unavailable";
1846
1880
  constructor() {
1847
1881
  super(
1848
1882
  "PAFI backend client not configured \u2014 set PAFI_BACKEND_URL, PAFI_ISSUER_ID, PAFI_API_KEY to enable mobile submit."
1849
1883
  );
1850
- this.name = "BundlerNotConfiguredError";
1851
1884
  }
1852
1885
  };
1853
- var BundlerRejectedError = class extends Error {
1886
+ var BundlerRejectedError = class extends PafiSdkError {
1854
1887
  code = "BUNDLER_REJECTED";
1888
+ httpStatus = "unprocessable";
1855
1889
  cause;
1856
1890
  constructor(message, cause) {
1857
1891
  super(message);
1858
- this.name = "BundlerRejectedError";
1859
1892
  this.cause = cause;
1860
1893
  }
1861
1894
  };
@@ -1911,13 +1944,22 @@ async function relayUserOp(params) {
1911
1944
  }
1912
1945
 
1913
1946
  // src/api/mobileHandlers.ts
1914
- var PendingUserOpNotFoundError = class extends Error {
1947
+ var PendingUserOpNotFoundError = class extends PafiSdkError {
1915
1948
  code = "PENDING_USEROP_NOT_FOUND";
1949
+ httpStatus = "not_found";
1916
1950
  constructor(lockId) {
1917
1951
  super(
1918
1952
  `No pending UserOp found for lockId ${lockId} \u2014 it may have expired or already been submitted.`
1919
1953
  );
1920
- this.name = "PendingUserOpNotFoundError";
1954
+ }
1955
+ };
1956
+ var PendingUserOpForbiddenError = class extends PafiSdkError {
1957
+ code = "PENDING_USEROP_FORBIDDEN";
1958
+ httpStatus = "forbidden";
1959
+ constructor(lockId) {
1960
+ super(
1961
+ `Pending UserOp ${lockId} does not belong to the authenticated user.`
1962
+ );
1921
1963
  }
1922
1964
  };
1923
1965
  async function handleMobilePrepare(params) {
@@ -1959,6 +2001,9 @@ async function handleMobileSubmit(params) {
1959
2001
  if (!entry) {
1960
2002
  throw new PendingUserOpNotFoundError(params.lockId);
1961
2003
  }
2004
+ if (getAddress8(entry.sender) !== getAddress8(params.authenticatedAddress)) {
2005
+ throw new PendingUserOpForbiddenError(params.lockId);
2006
+ }
1962
2007
  const variant = params.variant ?? "sponsored";
1963
2008
  const userOpJson = serializeEntryToJsonRpc(entry, params.signature, variant);
1964
2009
  const result = await relayUserOp({
@@ -1972,34 +2017,36 @@ async function handleMobileSubmit(params) {
1972
2017
  }
1973
2018
 
1974
2019
  // src/api/handlers/ptClaimHandler.ts
1975
- import { getAddress as getAddress8 } from "viem";
2020
+ import { getAddress as getAddress9 } from "viem";
1976
2021
  import {
1977
2022
  decodeBatchExecuteCalls,
1978
- getContractAddresses as getContractAddresses2
2023
+ getContractAddresses as getContractAddresses3
1979
2024
  } from "@pafi-dev/core";
1980
2025
 
1981
2026
  // src/issuer-state/types.ts
1982
- var IssuerStateError = class extends Error {
2027
+ var IssuerStateError = class extends PafiSdkError {
2028
+ httpStatus = "unprocessable";
2029
+ code;
2030
+ details;
2031
+ safeToRetry;
1983
2032
  constructor(code, message, details) {
1984
2033
  super(message);
1985
2034
  this.code = code;
1986
2035
  this.details = details;
1987
- this.name = "IssuerStateError";
2036
+ this.safeToRetry = code === "MINT_CAP_EXCEEDED";
1988
2037
  }
1989
- code;
1990
- details;
1991
2038
  };
1992
2039
 
1993
2040
  // src/api/handlers/ptClaimHandler.ts
1994
- var PTClaimError = class extends Error {
2041
+ var PTClaimError = class extends PafiSdkError {
2042
+ httpStatus = "unprocessable";
2043
+ code;
2044
+ details;
1995
2045
  constructor(code, message, details) {
1996
2046
  super(message);
1997
2047
  this.code = code;
1998
2048
  this.details = details;
1999
- this.name = "PTClaimError";
2000
2049
  }
2001
- code;
2002
- details;
2003
2050
  };
2004
2051
  var DEFAULT_LOCK_MS = 15 * 60 * 1e3;
2005
2052
  var DEFAULT_SIG_DEADLINE_SEC2 = 15 * 60;
@@ -2014,7 +2061,7 @@ var PTClaimHandler = class {
2014
2061
  };
2015
2062
  }
2016
2063
  async handle(request) {
2017
- if (getAddress8(request.authenticatedAddress) !== getAddress8(request.userAddress)) {
2064
+ if (getAddress9(request.authenticatedAddress) !== getAddress9(request.userAddress)) {
2018
2065
  throw new PTClaimError(
2019
2066
  "VALIDATION_FAILED",
2020
2067
  `userAddress (${request.userAddress}) does not match authenticated session (${request.authenticatedAddress})`
@@ -2037,7 +2084,7 @@ var PTClaimHandler = class {
2037
2084
  );
2038
2085
  }
2039
2086
  }
2040
- const { batchExecutor: batchExecutorAddress } = getContractAddresses2(
2087
+ const { batchExecutor: batchExecutorAddress } = getContractAddresses3(
2041
2088
  request.chainId
2042
2089
  );
2043
2090
  const lockId = await this.cfg.ledger.lockForMinting(
@@ -2117,15 +2164,15 @@ import {
2117
2164
  buildSwapWithGasDeduction,
2118
2165
  decodeBatchExecuteCalls as decodeBatchExecuteCalls2,
2119
2166
  findBestQuote,
2120
- getContractAddresses as getContractAddresses3
2167
+ getContractAddresses as getContractAddresses4
2121
2168
  } from "@pafi-dev/core";
2122
- var SwapError = class extends Error {
2169
+ var SwapError = class extends PafiSdkError {
2170
+ httpStatus = "unprocessable";
2171
+ code;
2123
2172
  constructor(code, message) {
2124
2173
  super(message);
2125
2174
  this.code = code;
2126
- this.name = "SwapError";
2127
2175
  }
2128
- code;
2129
2176
  };
2130
2177
  var DEFAULT_SLIPPAGE_BPS = 50;
2131
2178
  var DEFAULT_SWAP_DEADLINE_SEC = 5 * 60;
@@ -2144,7 +2191,7 @@ var SwapHandler = class {
2144
2191
  throw new SwapError("INVALID_AMOUNT", "amountIn must be positive");
2145
2192
  }
2146
2193
  const slippageBps = request.slippageBps ?? this.cfg.defaultSlippageBps;
2147
- const { usdt, pafiFeeRecipient, universalRouter } = getContractAddresses3(
2194
+ const { usdt, pafiFeeRecipient, universalRouter } = getContractAddresses4(
2148
2195
  request.chainId
2149
2196
  );
2150
2197
  const poolsResponse = await this.cfg.poolsProvider({
@@ -2259,15 +2306,17 @@ import {
2259
2306
  buildPerpDepositViaRelay,
2260
2307
  computeAccountId,
2261
2308
  decodeBatchExecuteCalls as decodeBatchExecuteCalls3,
2262
- getContractAddresses as getContractAddresses4
2309
+ getContractAddresses as getContractAddresses5
2263
2310
  } from "@pafi-dev/core";
2264
- var PerpDepositError = class extends Error {
2311
+ var PerpDepositError = class extends PafiSdkError {
2312
+ httpStatus = "unprocessable";
2313
+ code;
2314
+ safeToRetry;
2265
2315
  constructor(code, message) {
2266
2316
  super(message);
2267
2317
  this.code = code;
2268
- this.name = "PerpDepositError";
2318
+ this.safeToRetry = code === "RELAY_FEE_EXCEEDS_AMOUNT";
2269
2319
  }
2270
- code;
2271
2320
  };
2272
2321
  var DEFAULT_MAX_FEE_PREMIUM_BPS = 5e3;
2273
2322
  var PerpDepositHandler = class {
@@ -2291,7 +2340,7 @@ var PerpDepositHandler = class {
2291
2340
  `no Orderly Vault for chainId ${request.chainId}`
2292
2341
  );
2293
2342
  }
2294
- const { orderlyRelay: relayAddress, pafiFeeRecipient } = getContractAddresses4(request.chainId);
2343
+ const { orderlyRelay: relayAddress, pafiFeeRecipient } = getContractAddresses5(request.chainId);
2295
2344
  const [usdcAddress, brokerAllowed] = await Promise.all([
2296
2345
  this.cfg.provider.readContract({
2297
2346
  address: vault,
@@ -2380,7 +2429,7 @@ import {
2380
2429
  ENTRY_POINT_V08 as ENTRY_POINT_V082,
2381
2430
  buildEip7702Authorization,
2382
2431
  encodeBatchExecute,
2383
- getContractAddresses as getContractAddresses5,
2432
+ getContractAddresses as getContractAddresses6,
2384
2433
  serializeUserOpToJsonRpc as serializeUserOpToJsonRpc2
2385
2434
  } from "@pafi-dev/core";
2386
2435
  var DEFAULT_DELEGATE_GAS = {
@@ -2389,7 +2438,7 @@ var DEFAULT_DELEGATE_GAS = {
2389
2438
  preVerificationGas: 50000n
2390
2439
  };
2391
2440
  async function handleDelegateSubmit(params) {
2392
- const { batchExecutor } = getContractAddresses5(params.chainId);
2441
+ const { batchExecutor } = getContractAddresses6(params.chainId);
2393
2442
  const callData = encodeBatchExecute([]);
2394
2443
  const userOp = {
2395
2444
  sender: params.userAddress,
@@ -2454,7 +2503,7 @@ async function handleDelegateSubmit(params) {
2454
2503
  // src/api/quoteHelper.ts
2455
2504
  import {
2456
2505
  findBestQuote as findBestQuote2,
2457
- getContractAddresses as getContractAddresses6
2506
+ getContractAddresses as getContractAddresses7
2458
2507
  } from "@pafi-dev/core";
2459
2508
  var DEFAULT_DEADLINE_SECONDS = 300;
2460
2509
  async function quotePointTokenToUsdt(params) {
@@ -2479,7 +2528,7 @@ async function quotePointTokenToUsdt(params) {
2479
2528
  quoteError: "QUOTE_UNAVAILABLE"
2480
2529
  };
2481
2530
  }
2482
- const { usdt: usdtAddress } = getContractAddresses6(params.chainId);
2531
+ const { usdt: usdtAddress } = getContractAddresses7(params.chainId);
2483
2532
  let estimatedUsdtOut = 0n;
2484
2533
  let gasEstimate = 0n;
2485
2534
  try {
@@ -2519,6 +2568,31 @@ async function quotePointTokenToUsdt(params) {
2519
2568
  };
2520
2569
  }
2521
2570
 
2571
+ // src/api/errorMapper.ts
2572
+ function createSdkErrorMapper(factories) {
2573
+ return (err) => {
2574
+ if (!(err instanceof PafiSdkError)) {
2575
+ throw err;
2576
+ }
2577
+ const body = {
2578
+ code: err.code,
2579
+ message: err.message,
2580
+ details: err.details,
2581
+ safeToRetry: err.safeToRetry
2582
+ };
2583
+ switch (err.httpStatus) {
2584
+ case "not_found":
2585
+ throw factories.notFound(body);
2586
+ case "forbidden":
2587
+ throw factories.forbidden(body);
2588
+ case "unprocessable":
2589
+ throw factories.unprocessable(body);
2590
+ case "service_unavailable":
2591
+ throw factories.serviceUnavailable(body);
2592
+ }
2593
+ };
2594
+ }
2595
+
2522
2596
  // src/pools/subgraphPoolsProvider.ts
2523
2597
  import { isAddress } from "viem";
2524
2598
  import { PAFI_SUBGRAPH_URL } from "@pafi-dev/core";
@@ -3137,8 +3211,8 @@ var PafiBackendClient = class {
3137
3211
  };
3138
3212
 
3139
3213
  // src/config.ts
3140
- import { getAddress as getAddress9 } from "viem";
3141
- import { getContractAddresses as getContractAddresses7 } from "@pafi-dev/core";
3214
+ import { getAddress as getAddress10 } from "viem";
3215
+ import { getContractAddresses as getContractAddresses8 } from "@pafi-dev/core";
3142
3216
  function createIssuerService(config) {
3143
3217
  if (!config.provider) {
3144
3218
  throw new Error("createIssuerService: provider is required");
@@ -3158,7 +3232,7 @@ function createIssuerService(config) {
3158
3232
  "createIssuerService: at least one of pointTokenAddress / pointTokenAddresses is required"
3159
3233
  );
3160
3234
  }
3161
- const tokenAddresses = rawAddresses.map((a) => getAddress9(a));
3235
+ const tokenAddresses = rawAddresses.map((a) => getAddress10(a));
3162
3236
  const ledger = config.ledger;
3163
3237
  const sessionStore = config.sessionStore ?? new MemorySessionStore();
3164
3238
  const policy = config.policy ?? new DefaultPolicyEngine({ ledger });
@@ -3208,7 +3282,7 @@ function createIssuerService(config) {
3208
3282
  indexers.set(tokenAddress, new PointIndexer(indexerConfig));
3209
3283
  }
3210
3284
  const firstIndexer = indexers.get(tokenAddresses[0]);
3211
- const chainAddresses = getContractAddresses7(config.chainId);
3285
+ const chainAddresses = getContractAddresses8(config.chainId);
3212
3286
  const resolvedContracts = {
3213
3287
  batchExecutor: chainAddresses.batchExecutor,
3214
3288
  usdt: chainAddresses.usdt,
@@ -3256,11 +3330,11 @@ function createIssuerService(config) {
3256
3330
  }
3257
3331
 
3258
3332
  // src/issuer-state/validator.ts
3259
- import { getAddress as getAddress10 } from "viem";
3333
+ import { getAddress as getAddress11 } from "viem";
3260
3334
  import {
3261
3335
  POINT_TOKEN_V2_ABI as POINT_TOKEN_V2_ABI3,
3262
3336
  issuerRegistryGetIssuerFlatAbi,
3263
- getContractAddresses as getContractAddresses8
3337
+ getContractAddresses as getContractAddresses9
3264
3338
  } from "@pafi-dev/core";
3265
3339
  var ISSUER_RECORD_TTL_MS = 3e4;
3266
3340
  var IssuerStateValidator = class _IssuerStateValidator {
@@ -3278,7 +3352,7 @@ var IssuerStateValidator = class _IssuerStateValidator {
3278
3352
  * `CONTRACT_ADDRESSES` map for the given chain.
3279
3353
  */
3280
3354
  static forChain(provider, chainId) {
3281
- const { issuerRegistry } = getContractAddresses8(chainId);
3355
+ const { issuerRegistry } = getContractAddresses9(chainId);
3282
3356
  return new _IssuerStateValidator(provider, issuerRegistry);
3283
3357
  }
3284
3358
  /**
@@ -3287,7 +3361,7 @@ var IssuerStateValidator = class _IssuerStateValidator {
3287
3361
  */
3288
3362
  invalidate(pointToken) {
3289
3363
  if (pointToken) {
3290
- const key = getAddress10(pointToken);
3364
+ const key = getAddress11(pointToken);
3291
3365
  this.pointTokenIssuerCache.delete(key);
3292
3366
  this.stateCache.delete(key);
3293
3367
  this.inflight.delete(key);
@@ -3302,7 +3376,7 @@ var IssuerStateValidator = class _IssuerStateValidator {
3302
3376
  * The issuer field is set at `initialize()` and never changes.
3303
3377
  */
3304
3378
  async getIssuerAddressForPointToken(pointToken) {
3305
- const key = getAddress10(pointToken);
3379
+ const key = getAddress11(pointToken);
3306
3380
  const cached = this.pointTokenIssuerCache.get(key);
3307
3381
  if (cached) return cached;
3308
3382
  const issuer = await this.provider.readContract({
@@ -3310,15 +3384,15 @@ var IssuerStateValidator = class _IssuerStateValidator {
3310
3384
  abi: POINT_TOKEN_V2_ABI3,
3311
3385
  functionName: "issuer"
3312
3386
  });
3313
- this.pointTokenIssuerCache.set(key, getAddress10(issuer));
3314
- return getAddress10(issuer);
3387
+ this.pointTokenIssuerCache.set(key, getAddress11(issuer));
3388
+ return getAddress11(issuer);
3315
3389
  }
3316
3390
  /**
3317
3391
  * Read registry record + totalSupply, with 30s cache and in-flight
3318
3392
  * deduplication. Does NOT throw on inactive/missing — returns raw state.
3319
3393
  */
3320
3394
  async getIssuerState(pointToken) {
3321
- const tokenAddr = getAddress10(pointToken);
3395
+ const tokenAddr = getAddress11(pointToken);
3322
3396
  const now = Date.now();
3323
3397
  const cached = this.stateCache.get(tokenAddr);
3324
3398
  if (cached && cached.expiresAt > now) return cached.value;
@@ -3441,6 +3515,8 @@ export {
3441
3515
  PTRedeemHandler,
3442
3516
  PafiBackendClient,
3443
3517
  PafiBackendError,
3518
+ PafiSdkError,
3519
+ PendingUserOpForbiddenError,
3444
3520
  PendingUserOpNotFoundError,
3445
3521
  PerpDepositError,
3446
3522
  PerpDepositHandler,
@@ -3454,6 +3530,7 @@ export {
3454
3530
  authenticateRequest,
3455
3531
  createIssuerService,
3456
3532
  createNativePtQuoter,
3533
+ createSdkErrorMapper,
3457
3534
  createSubgraphNativeUsdtQuoter,
3458
3535
  createSubgraphPoolsProvider,
3459
3536
  handleClaimStatus,