@pafi-dev/issuer 0.33.0 → 0.35.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.cjs CHANGED
@@ -1373,9 +1373,9 @@ function createPafiEstimatorClient(config) {
1373
1373
  var InMemoryCursorStore = class _InMemoryCursorStore {
1374
1374
  cursor;
1375
1375
  /**
1376
- * Child stores keyed by `forKey()`. Each child has its own cursor
1377
- * (the H-05 fix), so a single InMemoryCursorStore can back N
1378
- * PointIndexers in tests / single-process callers.
1376
+ * Child stores keyed by `forKey()`. Each child has its own cursor,
1377
+ * so a single InMemoryCursorStore can back N PointIndexers in tests
1378
+ * / single-process callers.
1379
1379
  */
1380
1380
  children = /* @__PURE__ */ new Map();
1381
1381
  async load() {
@@ -2375,7 +2375,7 @@ var PTRedeemHandler = class {
2375
2375
  if (!config.supportedTokens) {
2376
2376
  throw new PTRedeemError(
2377
2377
  "UNSUPPORTED_POINT_TOKEN",
2378
- "PTRedeemHandler requires `supportedTokens` (issuer's allow-listed PointToken contracts). See audit PACI5-18."
2378
+ "PTRedeemHandler requires `supportedTokens` (issuer's allow-listed PointToken contracts)."
2379
2379
  );
2380
2380
  }
2381
2381
  this.supportedTokens = config.supportedTokens;
@@ -2389,7 +2389,7 @@ var PTRedeemHandler = class {
2389
2389
  if (this.signatureDeadlineSeconds * 1e3 > maxAllowedSignatureMs) {
2390
2390
  throw new PTRedeemError(
2391
2391
  "INVALID_AMOUNT",
2392
- `PTRedeemHandler config: signatureDeadlineSeconds (${this.signatureDeadlineSeconds}s) must be at most redeemLockDurationMs - safety margin = ${maxAllowedSignatureMs / 1e3}s (redeemLockDurationMs=${this.redeemLockDurationMs / 1e3}s, safety=${M11_SAFETY_MARGIN_MS / 1e3}s). See audit M-11.`
2392
+ `PTRedeemHandler config: signatureDeadlineSeconds (${this.signatureDeadlineSeconds}s) must be at most redeemLockDurationMs - safety margin = ${maxAllowedSignatureMs / 1e3}s (redeemLockDurationMs=${this.redeemLockDurationMs / 1e3}s, safety=${M11_SAFETY_MARGIN_MS / 1e3}s).`
2393
2393
  );
2394
2394
  }
2395
2395
  if (config.redemptionService) {
@@ -2650,13 +2650,13 @@ var DEFAULT_STATUS_CONFIRMATIONS = 3;
2650
2650
  async function isReceiptPastConfirmations(receipt, provider, confirmations, onWarning, handlerName) {
2651
2651
  if (!provider) {
2652
2652
  onWarning?.(
2653
- `${handlerName}: provider missing \u2014 cannot enforce confirmation depth; deferring receipt fallback to on-chain indexer (audit PACI5-13).`
2653
+ `${handlerName}: provider missing \u2014 cannot enforce confirmation depth; deferring receipt fallback to on-chain indexer.`
2654
2654
  );
2655
2655
  return false;
2656
2656
  }
2657
2657
  if (!receipt.blockNumber) {
2658
2658
  onWarning?.(
2659
- `${handlerName}: receipt has no blockNumber \u2014 cannot enforce confirmation depth; deferring to indexer (audit PACI5-13).`
2659
+ `${handlerName}: receipt has no blockNumber \u2014 cannot enforce confirmation depth; deferring to indexer.`
2660
2660
  );
2661
2661
  return false;
2662
2662
  }
@@ -2666,7 +2666,7 @@ async function isReceiptPastConfirmations(receipt, provider, confirmations, onWa
2666
2666
  receiptBlock = BigInt(receipt.blockNumber);
2667
2667
  } catch {
2668
2668
  onWarning?.(
2669
- `${handlerName}: malformed receipt blockNumber (${receipt.blockNumber}) \u2014 deferring to indexer (audit PACI5-13).`
2669
+ `${handlerName}: malformed receipt blockNumber (${receipt.blockNumber}) \u2014 deferring to indexer.`
2670
2670
  );
2671
2671
  return false;
2672
2672
  }
@@ -2675,7 +2675,7 @@ async function isReceiptPastConfirmations(receipt, provider, confirmations, onWa
2675
2675
  head = await provider.getBlockNumber();
2676
2676
  } catch (err) {
2677
2677
  onWarning?.(
2678
- `${handlerName}: getBlockNumber failed (${err instanceof Error ? err.message : String(err)}) \u2014 deferring to indexer (audit PACI5-13).`
2678
+ `${handlerName}: getBlockNumber failed (${err instanceof Error ? err.message : String(err)}) \u2014 deferring to indexer.`
2679
2679
  );
2680
2680
  return false;
2681
2681
  }
@@ -2733,7 +2733,7 @@ async function handleClaimStatus(params) {
2733
2733
  if (receipt.success && receipt.txHash) {
2734
2734
  if (!lock.tokenAddress) {
2735
2735
  params.onWarning?.(
2736
- `handleClaimStatus: lock ${lock.lockId} has no tokenAddress; falling back to status-only flip (PACI5-24 defence degraded). Migrate the ledger to the multi-token schema.`
2736
+ `handleClaimStatus: lock ${lock.lockId} has no tokenAddress; falling back to status-only flip \u2014 atomic debit+flip cannot run on a legacy single-token row. Migrate the ledger to the multi-token schema.`
2737
2737
  );
2738
2738
  await params.ledger.updateMintStatus(lock.lockId, "MINTED", receipt.txHash).catch((err) => {
2739
2739
  params.onWarning?.(
@@ -2981,8 +2981,8 @@ async function prepareMobileUserOp(params) {
2981
2981
  verificationGasLimit: fallback.userOp.verificationGasLimit.toString(),
2982
2982
  preVerificationGas: fallback.userOp.preVerificationGas.toString(),
2983
2983
  userOpHash: fallback.userOpHash,
2984
- // Audit PACI5-21 — carry the fallback-specific lockId so submit
2985
- // can bind the fallback userOpHash to the correct ledger row.
2984
+ // Carry the fallback-specific lockId so submit can bind the
2985
+ // fallback userOpHash to the correct ledger row.
2986
2986
  lockId: params.lockIdFallback
2987
2987
  };
2988
2988
  }
@@ -3255,7 +3255,7 @@ var PTClaimHandler = class {
3255
3255
  if (!config.supportedTokens) {
3256
3256
  throw new PTClaimError(
3257
3257
  "UNSUPPORTED_POINT_TOKEN",
3258
- "PTClaimHandler requires `supportedTokens` (issuer's allow-listed PointToken contracts). See audit PACI5-18."
3258
+ "PTClaimHandler requires `supportedTokens` (issuer's allow-listed PointToken contracts)."
3259
3259
  );
3260
3260
  }
3261
3261
  const lockDurationMs = config.lockDurationMs ?? DEFAULT_LOCK_MS;
@@ -3264,7 +3264,7 @@ var PTClaimHandler = class {
3264
3264
  if (signatureDeadlineSeconds * 1e3 > maxAllowedSignatureMs) {
3265
3265
  throw new PTClaimError(
3266
3266
  "VALIDATION_FAILED",
3267
- `PTClaimHandler config: signatureDeadlineSeconds (${signatureDeadlineSeconds}s) must be at most lockDurationMs - safety margin = ${maxAllowedSignatureMs / 1e3}s (lockDurationMs=${lockDurationMs / 1e3}s, safety=${M11_SAFETY_MARGIN_MS2 / 1e3}s). See audit M-11.`,
3267
+ `PTClaimHandler config: signatureDeadlineSeconds (${signatureDeadlineSeconds}s) must be at most lockDurationMs - safety margin = ${maxAllowedSignatureMs / 1e3}s (lockDurationMs=${lockDurationMs / 1e3}s, safety=${M11_SAFETY_MARGIN_MS2 / 1e3}s).`,
3268
3268
  {
3269
3269
  lockDurationMs,
3270
3270
  signatureDeadlineSeconds,
@@ -3378,6 +3378,13 @@ var PTClaimHandler = class {
3378
3378
  callData: previewUserOp.callData
3379
3379
  }
3380
3380
  }) : 0n;
3381
+ if (feeAmount > 0n && feeAmount >= request.amount) {
3382
+ throw new PTClaimError(
3383
+ "INVALID_AMOUNT",
3384
+ `fee (${feeAmount}) must be strictly less than claim amount (${request.amount})`,
3385
+ { feeAmount: feeAmount.toString(), amount: request.amount.toString() }
3386
+ );
3387
+ }
3381
3388
  const domainName = await this.cfg.domainResolver.resolve(
3382
3389
  request.pointTokenAddress
3383
3390
  );
@@ -3984,8 +3991,6 @@ var IssuerApiAdapter = class {
3984
3991
  userAddress: authenticatedAddress,
3985
3992
  ledger: this.cfg.ledger,
3986
3993
  pafiBackendClient: this.cfg.pafiBackendClient,
3987
- // Audit PACI5-13 — pass the same provider the indexers use so
3988
- // the receipt fallback gates on the same reorg depth.
3989
3994
  provider: this.cfg.provider,
3990
3995
  onWarning: this.cfg.onWarning
3991
3996
  });
@@ -3996,7 +4001,6 @@ var IssuerApiAdapter = class {
3996
4001
  userAddress: authenticatedAddress,
3997
4002
  ledger: this.cfg.ledger,
3998
4003
  pafiBackendClient: this.cfg.pafiBackendClient,
3999
- // Audit PACI5-13 — see claimStatus comment.
4000
4004
  provider: this.cfg.provider,
4001
4005
  onWarning: this.cfg.onWarning
4002
4006
  });
@@ -5085,7 +5089,7 @@ async function createIssuerService(config) {
5085
5089
  const sharedCursorWithMultipleTokens = baseCursorStore !== void 0 && typeof baseCursorStore.forKey !== "function" && tokenAddresses.length > 1;
5086
5090
  if (sharedCursorWithMultipleTokens) {
5087
5091
  console.warn(
5088
- `[@pafi-dev/issuer] cursorStore lacks forKey() and ${tokenAddresses.length} PointTokens are configured. All PointIndexers will share one cursor row, causing token-skipping (audit finding H-05). Implement IIndexerCursorStore.forKey to return per-token derived stores. This permissive path will be removed in a future major release.`
5092
+ `[@pafi-dev/issuer] cursorStore lacks forKey() and ${tokenAddresses.length} PointTokens are configured. All PointIndexers will share one cursor row, causing token-skipping. Implement IIndexerCursorStore.forKey to return per-token derived stores. This permissive path will be removed in a future major release.`
5089
5093
  );
5090
5094
  }
5091
5095
  const indexers = /* @__PURE__ */ new Map();
@@ -5176,7 +5180,7 @@ async function createIssuerService(config) {
5176
5180
  const lock = config.indexer.singletonLock;
5177
5181
  if (!lock) {
5178
5182
  console.warn(
5179
- "[@pafi-dev/issuer] indexer.autoStart=true without singletonLock \u2014 this is UNSAFE in multi-replica deployments (audit finding H-04). Either set replicas=1 + INDEXER_AUTOSTART=false on non-leader pods, or pass `singletonLock: makePostgresSingletonLock(dataSource)`. This permissive path will be removed in a future major release."
5183
+ "[@pafi-dev/issuer] indexer.autoStart=true without singletonLock \u2014 this is UNSAFE in multi-replica deployments. Either set replicas=1 + INDEXER_AUTOSTART=false on non-leader pods, or pass `singletonLock: makePostgresSingletonLock(dataSource)`. This permissive path will be removed in a future major release."
5180
5184
  );
5181
5185
  for (const idx of indexers.values()) {
5182
5186
  idx.start();
@@ -5210,7 +5214,7 @@ async function createIssuerService(config) {
5210
5214
  // src/issuer-state/validator.ts
5211
5215
  var import_viem16 = require("viem");
5212
5216
  var import_core20 = require("@pafi-dev/core");
5213
- var ISSUER_RECORD_TTL_MS = 3e4;
5217
+ var ISSUER_RECORD_TTL_MS = 1e4;
5214
5218
  var IssuerStateValidator = class _IssuerStateValidator {
5215
5219
  constructor(provider, registryAddress) {
5216
5220
  this.provider = provider;
@@ -5231,7 +5235,9 @@ var IssuerStateValidator = class _IssuerStateValidator {
5231
5235
  }
5232
5236
  /**
5233
5237
  * Invalidate cached state for one PointToken, or everything if omitted.
5234
- * Call after admin txs that change registry or cap settings.
5238
+ * Call after admin txs that change registry or cap settings — closes
5239
+ * the split-brain window described
5240
+ * passive TTL. Idempotent: safe to call when no entry exists.
5235
5241
  */
5236
5242
  invalidate(pointToken) {
5237
5243
  if (pointToken) {
@@ -5404,7 +5410,7 @@ var MemoryRedemptionHistoryStore = class {
5404
5410
  };
5405
5411
 
5406
5412
  // src/index.ts
5407
- var PAFI_ISSUER_SDK_VERSION = true ? "0.33.0" : "dev";
5413
+ var PAFI_ISSUER_SDK_VERSION = true ? "0.35.0" : "dev";
5408
5414
  // Annotate the CommonJS export names for ESM import in node:
5409
5415
  0 && (module.exports = {
5410
5416
  AdapterMisconfiguredError,