@pafi-dev/issuer 0.12.7 → 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/dist/index.js CHANGED
@@ -779,8 +779,8 @@ var RelayService = class {
779
779
  * provides a pre-signed `BurnRequest` + sig bytes (typically from
780
780
  * `PTRedeemHandler`).
781
781
  *
782
- * Direct burn (no sig) was dropped in v1.4 — every burn now goes
783
- * through the issuer-signed `BurnRequest` path.
782
+ * Direct burn (no sig) is not used — every burn goes through the
783
+ * issuer-signed `BurnRequest` path.
784
784
  */
785
785
  async prepareBurn(params) {
786
786
  if (!params.pointTokenAddress) {
@@ -1064,7 +1064,7 @@ var PointIndexer = class {
1064
1064
  // Event fetching — two modes (wrapper vs direct)
1065
1065
  // -------------------------------------------------------------------------
1066
1066
  /**
1067
- * Wrapper mode (v1.6): listen for `MintWithFee` on the wrapper,
1067
+ * Wrapper mode: listen for `MintWithFee` on the wrapper,
1068
1068
  * filtered to events for THIS pointToken only. The event's `to` field
1069
1069
  * is the actual end user, and `grossAmount` matches the lock amount.
1070
1070
  */
@@ -1349,7 +1349,6 @@ import {
1349
1349
  getMintFeeBps,
1350
1350
  getMintRequestNonce,
1351
1351
  getPointTokenBalance,
1352
- getReceiverConsentNonce,
1353
1352
  isMinter
1354
1353
  } from "@pafi-dev/core";
1355
1354
  var IssuerApiHandlers = class _IssuerApiHandlers {
@@ -1592,9 +1591,8 @@ var IssuerApiHandlers = class _IssuerApiHandlers {
1592
1591
  /**
1593
1592
  * `GET /user?chainId=<id>&user=<addr>&pointToken=<addr>`
1594
1593
  *
1595
- * Returns per-user state the frontend needs to build a fresh
1596
- * `ReceiverConsent`: on-chain nonces + minter status + off-chain
1597
- * balance.
1594
+ * Returns per-user state the frontend needs to build a fresh mint:
1595
+ * on-chain nonces + minter status + off-chain balance.
1598
1596
  */
1599
1597
  async handleUser(userAddress, request) {
1600
1598
  if (request.chainId !== this.chainId) {
@@ -1621,16 +1619,14 @@ var IssuerApiHandlers = class _IssuerApiHandlers {
1621
1619
  { requested: pointToken }
1622
1620
  );
1623
1621
  }
1624
- const [mintRequestNonce, receiverConsentNonce, offChainBalance, onChainBalance, minter] = await Promise.all([
1622
+ const [mintRequestNonce, offChainBalance, onChainBalance, minter] = await Promise.all([
1625
1623
  getMintRequestNonce(this.provider, pointToken, normalizedAuthed),
1626
- getReceiverConsentNonce(this.provider, pointToken, normalizedAuthed),
1627
1624
  this.ledger.getBalance(normalizedAuthed, pointToken),
1628
1625
  getPointTokenBalance(this.provider, pointToken, normalizedAuthed),
1629
1626
  isMinter(this.provider, pointToken, normalizedAuthed)
1630
1627
  ]);
1631
1628
  return {
1632
1629
  mintRequestNonce,
1633
- receiverConsentNonce,
1634
1630
  offChainBalance,
1635
1631
  onChainBalance,
1636
1632
  totalBalance: offChainBalance + onChainBalance,
@@ -2209,38 +2205,42 @@ function mergePaymasterFields(userOp, paymasterFields) {
2209
2205
  }
2210
2206
  return merged;
2211
2207
  }
2212
- async function prepareMobileUserOp(params) {
2208
+ function applyPaymasterGasEstimates(partialUserOp, paymasterFields, chainId) {
2213
2209
  const userOp = mergePaymasterFields(
2214
- params.partialUserOp,
2215
- params.paymasterFields
2210
+ partialUserOp,
2211
+ paymasterFields
2216
2212
  );
2217
- const userOpHash = computeUserOpHash(userOp, params.chainId);
2218
- const typedData = serializeUserOpTypedData(
2219
- buildUserOpTypedData(userOp, params.chainId)
2213
+ return {
2214
+ userOp,
2215
+ userOpHash: computeUserOpHash(userOp, chainId),
2216
+ typedData: serializeUserOpTypedData(buildUserOpTypedData(userOp, chainId))
2217
+ };
2218
+ }
2219
+ async function prepareMobileUserOp(params) {
2220
+ const sponsored = applyPaymasterGasEstimates(
2221
+ params.partialUserOp,
2222
+ params.paymasterFields,
2223
+ params.chainId
2220
2224
  );
2225
+ const { userOp, userOpHash } = sponsored;
2221
2226
  let fallback;
2222
2227
  let fallbackEntry;
2223
2228
  if (params.partialUserOpFallback) {
2224
- const fallbackUserOp = {
2225
- ...params.partialUserOpFallback,
2226
- maxFeePerGas: userOp.maxFeePerGas,
2227
- maxPriorityFeePerGas: userOp.maxPriorityFeePerGas
2228
- };
2229
- const fallbackHash = computeUserOpHash(fallbackUserOp, params.chainId);
2230
- const fallbackTypedData = serializeUserOpTypedData(
2231
- buildUserOpTypedData(fallbackUserOp, params.chainId)
2229
+ fallback = applyPaymasterGasEstimates(
2230
+ {
2231
+ ...params.partialUserOpFallback,
2232
+ maxFeePerGas: userOp.maxFeePerGas,
2233
+ maxPriorityFeePerGas: userOp.maxPriorityFeePerGas
2234
+ },
2235
+ void 0,
2236
+ params.chainId
2232
2237
  );
2233
- fallback = {
2234
- userOp: fallbackUserOp,
2235
- userOpHash: fallbackHash,
2236
- typedData: fallbackTypedData
2237
- };
2238
2238
  fallbackEntry = {
2239
- callData: fallbackUserOp.callData,
2240
- callGasLimit: fallbackUserOp.callGasLimit.toString(),
2241
- verificationGasLimit: fallbackUserOp.verificationGasLimit.toString(),
2242
- preVerificationGas: fallbackUserOp.preVerificationGas.toString(),
2243
- userOpHash: fallbackHash
2239
+ callData: fallback.userOp.callData,
2240
+ callGasLimit: fallback.userOp.callGasLimit.toString(),
2241
+ verificationGasLimit: fallback.userOp.verificationGasLimit.toString(),
2242
+ preVerificationGas: fallback.userOp.preVerificationGas.toString(),
2243
+ userOpHash: fallback.userOpHash
2244
2244
  };
2245
2245
  }
2246
2246
  const entry = {
@@ -2262,7 +2262,7 @@ async function prepareMobileUserOp(params) {
2262
2262
  };
2263
2263
  await params.store.save(params.lockId, entry, params.ttlSeconds);
2264
2264
  return {
2265
- sponsored: { userOp, userOpHash, typedData },
2265
+ sponsored,
2266
2266
  fallback,
2267
2267
  entry
2268
2268
  };
@@ -2764,8 +2764,6 @@ import {
2764
2764
  ENTRY_POINT_V08 as ENTRY_POINT_V082,
2765
2765
  buildDelegationUserOp,
2766
2766
  buildEip7702Authorization,
2767
- computeUserOpHash as computeUserOpHash2,
2768
- buildUserOpTypedData as buildUserOpTypedData2,
2769
2767
  getContractAddresses as getContractAddresses5,
2770
2768
  serializeUserOpToJsonRpc as serializeUserOpToJsonRpc2
2771
2769
  } from "@pafi-dev/core";
@@ -2811,22 +2809,13 @@ async function handleDelegatePrepare(params) {
2811
2809
  eip7702Auth: authorization,
2812
2810
  onWarning: params.onWarning
2813
2811
  });
2814
- const merged = {
2815
- sender: userOp.sender,
2816
- nonce: userOp.nonce,
2817
- callData: userOp.callData,
2818
- callGasLimit: paymasterFields?.callGasLimit ?? userOp.callGasLimit,
2819
- verificationGasLimit: paymasterFields?.verificationGasLimit ?? userOp.verificationGasLimit,
2820
- preVerificationGas: paymasterFields?.preVerificationGas ?? userOp.preVerificationGas,
2821
- maxFeePerGas: paymasterFields?.maxFeePerGas ?? userOp.maxFeePerGas,
2822
- maxPriorityFeePerGas: paymasterFields?.maxPriorityFeePerGas ?? userOp.maxPriorityFeePerGas,
2823
- paymaster: paymasterFields?.paymaster,
2824
- paymasterVerificationGasLimit: paymasterFields?.paymasterVerificationGasLimit,
2825
- paymasterPostOpGasLimit: paymasterFields?.paymasterPostOpGasLimit,
2826
- paymasterData: paymasterFields?.paymasterData
2827
- };
2828
- const userOpHash = computeUserOpHash2(merged, params.chainId);
2829
- const typed = buildUserOpTypedData2(merged, params.chainId);
2812
+ const prepared = applyPaymasterGasEstimates(
2813
+ userOp,
2814
+ paymasterFields,
2815
+ params.chainId
2816
+ );
2817
+ const merged = prepared.userOp;
2818
+ const userOpHash = prepared.userOpHash;
2830
2819
  await params.store.save(
2831
2820
  params.lockId,
2832
2821
  {
@@ -2855,7 +2844,7 @@ async function handleDelegatePrepare(params) {
2855
2844
  return {
2856
2845
  lockId: params.lockId,
2857
2846
  userOpHash,
2858
- typedData: serializeUserOpTypedData(typed),
2847
+ typedData: prepared.typedData,
2859
2848
  expiresInSeconds: params.ttlSeconds,
2860
2849
  isSponsored: !!paymasterFields
2861
2850
  };
@@ -2966,7 +2955,6 @@ var IssuerApiAdapter = class {
2966
2955
  );
2967
2956
  return {
2968
2957
  mintRequestNonce: result.mintRequestNonce.toString(),
2969
- receiverConsentNonce: result.receiverConsentNonce.toString(),
2970
2958
  offChainBalance: result.offChainBalance.toString(),
2971
2959
  onChainBalance: result.onChainBalance.toString(),
2972
2960
  totalBalance: result.totalBalance.toString(),
@@ -3317,6 +3305,7 @@ var IssuerApiAdapter = class {
3317
3305
  import { isAddress } from "viem";
3318
3306
  import { PAFI_SUBGRAPH_URL } from "@pafi-dev/core";
3319
3307
  var DEFAULT_CACHE_TTL_MS = 3e4;
3308
+ var MAX_REASONABLE_FEE_TIER = 1e6;
3320
3309
  var POOL_QUERY = `
3321
3310
  query GetPoolForPointToken($id: ID!) {
3322
3311
  pafiToken(id: $id) {
@@ -3324,8 +3313,6 @@ var POOL_QUERY = `
3324
3313
  pool {
3325
3314
  id
3326
3315
  feeTier
3327
- tickSpacing
3328
- hooks
3329
3316
  token0 { id }
3330
3317
  token1 { id }
3331
3318
  }
@@ -3350,12 +3337,20 @@ function createSubgraphPoolsProvider(config = {}) {
3350
3337
  const cacheTtl = config.cacheTtlMs ?? DEFAULT_CACHE_TTL_MS;
3351
3338
  const fetchImpl = config.fetchImpl ?? globalThis.fetch;
3352
3339
  const now = config.now ?? (() => Date.now());
3340
+ const onError = config.onError;
3353
3341
  const cache = /* @__PURE__ */ new Map();
3354
3342
  if (!fetchImpl) {
3355
3343
  throw new Error(
3356
3344
  "createSubgraphPoolsProvider: no fetch implementation available \u2014 pass `fetchImpl` or run on Node 18+"
3357
3345
  );
3358
3346
  }
3347
+ const reportError = (err) => {
3348
+ if (!onError) return;
3349
+ try {
3350
+ onError(err);
3351
+ } catch {
3352
+ }
3353
+ };
3359
3354
  return async (request) => {
3360
3355
  const cacheKey = `${request.chainId}:${request.pointTokenAddress.toLowerCase()}`;
3361
3356
  if (cacheTtl > 0) {
@@ -3367,7 +3362,8 @@ function createSubgraphPoolsProvider(config = {}) {
3367
3362
  const pools = await fetchPoolsFromSubgraph(
3368
3363
  fetchImpl,
3369
3364
  subgraphUrl,
3370
- request.pointTokenAddress
3365
+ request.pointTokenAddress,
3366
+ reportError
3371
3367
  );
3372
3368
  if (cacheTtl > 0) {
3373
3369
  cache.set(cacheKey, {
@@ -3378,7 +3374,7 @@ function createSubgraphPoolsProvider(config = {}) {
3378
3374
  return { pools };
3379
3375
  };
3380
3376
  }
3381
- async function fetchPoolsFromSubgraph(fetchImpl, subgraphUrl, pointTokenAddress) {
3377
+ async function fetchPoolsFromSubgraph(fetchImpl, subgraphUrl, pointTokenAddress, reportError) {
3382
3378
  let response;
3383
3379
  try {
3384
3380
  response = await fetchImpl(subgraphUrl, {
@@ -3390,24 +3386,38 @@ async function fetchPoolsFromSubgraph(fetchImpl, subgraphUrl, pointTokenAddress)
3390
3386
  })
3391
3387
  });
3392
3388
  } catch (err) {
3389
+ const error = err instanceof Error ? err : new Error(String(err));
3393
3390
  console.warn(
3394
3391
  "[subgraphPoolsProvider] subgraph unreachable:",
3395
- err.message
3392
+ error.message
3396
3393
  );
3394
+ reportError(error);
3397
3395
  return [];
3398
3396
  }
3399
3397
  if (!response.ok) {
3400
- console.warn(
3401
- `[subgraphPoolsProvider] subgraph returned ${response.status}`
3398
+ const error = new Error(
3399
+ `subgraph returned HTTP ${response.status}`
3402
3400
  );
3401
+ console.warn(`[subgraphPoolsProvider] ${error.message}`);
3402
+ reportError(error);
3403
3403
  return [];
3404
3404
  }
3405
- const json = await response.json();
3406
- if (json.errors && json.errors.length > 0) {
3405
+ let json;
3406
+ try {
3407
+ json = await response.json();
3408
+ } catch (err) {
3409
+ const error = err instanceof Error ? err : new Error(String(err));
3407
3410
  console.warn(
3408
- "[subgraphPoolsProvider] subgraph errors:",
3409
- json.errors.map((e) => e.message).join("; ")
3411
+ "[subgraphPoolsProvider] subgraph returned non-JSON:",
3412
+ error.message
3410
3413
  );
3414
+ reportError(error);
3415
+ return [];
3416
+ }
3417
+ if (json.errors && json.errors.length > 0) {
3418
+ const msg = json.errors.map((e) => e.message).join("; ");
3419
+ console.warn("[subgraphPoolsProvider] subgraph errors:", msg);
3420
+ reportError(new Error(`subgraph GraphQL errors: ${msg}`));
3411
3421
  return [];
3412
3422
  }
3413
3423
  const token = json.data?.pafiToken;
@@ -3415,40 +3425,35 @@ async function fetchPoolsFromSubgraph(fetchImpl, subgraphUrl, pointTokenAddress)
3415
3425
  return [];
3416
3426
  }
3417
3427
  const { pool } = token;
3418
- if (!isAddress(pool.hooks)) {
3419
- console.error(
3420
- "[PAFI] SubgraphPoolsProvider: invalid hooks address in response:",
3421
- pool.hooks,
3422
- "\u2014 skipping pool"
3423
- );
3424
- return [];
3425
- }
3426
3428
  if (!isAddress(pool.token0.id) || !isAddress(pool.token1.id)) {
3427
- console.error(
3428
- "[PAFI] SubgraphPoolsProvider: invalid token address in response \u2014 skipping pool"
3429
+ const error = new Error(
3430
+ "[PAFI] SubgraphPoolsProvider: invalid token address in response"
3429
3431
  );
3432
+ console.error(error.message, "\u2014 skipping pool");
3433
+ reportError(error);
3430
3434
  return [];
3431
3435
  }
3432
- if (!Number.isFinite(Number(pool.feeTier)) || !Number.isFinite(Number(pool.tickSpacing))) {
3433
- console.error(
3434
- "[PAFI] SubgraphPoolsProvider: invalid feeTier/tickSpacing \u2014 skipping pool"
3436
+ const feeNum = Number(pool.feeTier);
3437
+ if (!Number.isInteger(feeNum) || feeNum < 0 || feeNum >= MAX_REASONABLE_FEE_TIER) {
3438
+ const error = new Error(
3439
+ `[PAFI] SubgraphPoolsProvider: invalid feeTier value: ${pool.feeTier}`
3435
3440
  );
3441
+ console.error(error.message, "\u2014 skipping pool");
3442
+ reportError(error);
3436
3443
  return [];
3437
3444
  }
3438
- const [currency0, currency1] = sortCurrencies(
3445
+ const [token0, token1] = sortTokens(
3439
3446
  pool.token0.id,
3440
3447
  pool.token1.id
3441
3448
  );
3442
3449
  const poolKey = {
3443
- currency0,
3444
- currency1,
3445
- fee: Number(pool.feeTier),
3446
- tickSpacing: Number(pool.tickSpacing),
3447
- hooks: pool.hooks
3450
+ token0,
3451
+ token1,
3452
+ fee: feeNum
3448
3453
  };
3449
3454
  return [poolKey];
3450
3455
  }
3451
- function sortCurrencies(a, b) {
3456
+ function sortTokens(a, b) {
3452
3457
  return a.toLowerCase() < b.toLowerCase() ? [a, b] : [b, a];
3453
3458
  }
3454
3459
 
@@ -3676,52 +3681,6 @@ function parseBigDecimalTo18(s) {
3676
3681
  return BigInt(whole + padded);
3677
3682
  }
3678
3683
 
3679
- // src/balance/balanceAggregator.ts
3680
- import { getPointTokenBalance as getPointTokenBalance3 } from "@pafi-dev/core";
3681
- var BalanceAggregator = class {
3682
- provider;
3683
- ledger;
3684
- constructor(config) {
3685
- if (!config.provider) {
3686
- throw new Error("BalanceAggregator: provider is required");
3687
- }
3688
- if (!config.ledger) {
3689
- throw new Error("BalanceAggregator: ledger is required");
3690
- }
3691
- this.provider = config.provider;
3692
- this.ledger = config.ledger;
3693
- }
3694
- /**
3695
- * Combined balance for a single (user, token) pair. Fetches off-chain
3696
- * + on-chain in parallel.
3697
- */
3698
- async getCombinedBalance(user, pointToken) {
3699
- const [offChain, onChain] = await Promise.all([
3700
- this.ledger.getBalance(user, pointToken),
3701
- getPointTokenBalance3(this.provider, pointToken, user)
3702
- ]);
3703
- return {
3704
- offChain,
3705
- onChain,
3706
- total: offChain + onChain
3707
- };
3708
- }
3709
- /**
3710
- * Combined balance for multiple tokens owned by the same user. Runs
3711
- * all lookups in parallel. Returns a Map keyed by the token address
3712
- * (same casing as supplied — caller should normalize if needed).
3713
- */
3714
- async getCombinedBalanceMulti(user, pointTokens) {
3715
- const entries = await Promise.all(
3716
- pointTokens.map(async (token) => {
3717
- const balance = await this.getCombinedBalance(user, token);
3718
- return [token, balance];
3719
- })
3720
- );
3721
- return new Map(entries);
3722
- }
3723
- };
3724
-
3725
3684
  // src/pafi-backend/client.ts
3726
3685
  import { getPafiServiceUrls } from "@pafi-dev/core";
3727
3686
  function extractPafiErrorFields(json, status) {
@@ -4288,14 +4247,12 @@ function createIssuerService(config) {
4288
4247
  }
4289
4248
  indexers.set(tokenAddress, new PointIndexer(indexerConfig));
4290
4249
  }
4291
- const firstIndexer = indexers.get(tokenAddresses[0]);
4292
4250
  const chainAddresses = getContractAddresses7(config.chainId);
4293
4251
  const resolvedContracts = {
4294
4252
  batchExecutor: chainAddresses.batchExecutor,
4295
4253
  usdt: chainAddresses.usdt,
4296
4254
  issuerRegistry: chainAddresses.issuerRegistry,
4297
4255
  mintingOracle: chainAddresses.mintingOracle,
4298
- pafiHook: chainAddresses.pafiHook,
4299
4256
  ...config.contracts
4300
4257
  };
4301
4258
  if (resolvedWrapperAddress !== void 0) {
@@ -4348,7 +4305,6 @@ function createIssuerService(config) {
4348
4305
  relay: relayService,
4349
4306
  fee: feeManager,
4350
4307
  indexers,
4351
- indexer: firstIndexer,
4352
4308
  api: handlers,
4353
4309
  redemption
4354
4310
  };
@@ -4561,12 +4517,11 @@ var MemoryRedemptionHistoryStore = class {
4561
4517
  };
4562
4518
 
4563
4519
  // src/index.ts
4564
- var PAFI_ISSUER_SDK_VERSION = true ? "0.12.7" : "dev";
4520
+ var PAFI_ISSUER_SDK_VERSION = true ? "0.15.0" : "dev";
4565
4521
  export {
4566
4522
  AdapterMisconfiguredError,
4567
4523
  AuthError,
4568
4524
  AuthService,
4569
- BalanceAggregator,
4570
4525
  BundlerNotConfiguredError,
4571
4526
  BundlerRejectedError,
4572
4527
  BurnIndexer,
@@ -4608,6 +4563,7 @@ export {
4608
4563
  SDK_ERROR_HTTP_STATUS_CODE,
4609
4564
  SettlementClient,
4610
4565
  ValidationError,
4566
+ applyPaymasterGasEstimates,
4611
4567
  authenticateRequest,
4612
4568
  buildErrorEnvelope,
4613
4569
  buildSdkErrorBody,